2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2009 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 OSes. 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 * Send a XATTR stream to the SD.
79 static bool send_xattr_stream(JCR *jcr, int stream)
81 BSOCK *sd = jcr->store_bsock;
83 #ifdef FD_NO_SEND_TEST
90 if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
91 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
98 * Send the buffer to the storage deamon
100 Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
102 sd->msg = jcr->xattr_data;
103 sd->msglen = jcr->xattr_data_len;
107 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
113 jcr->JobBytes += sd->msglen;
115 if (!sd->signal(BNET_EOD)) {
116 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
122 Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
128 * This is a supported OS, See what kind of interface we should use.
129 * Start with the generic interface used by most OS-es.
131 #if defined(HAVE_DARWIN_OS) \
132 || defined(HAVE_FREEBSD_OS) \
133 || defined(HAVE_LINUX_OS) \
134 || defined(HAVE_NETBSD_OS)
136 #ifdef HAVE_SYS_XATTR_H
137 #include <sys/xattr.h>
141 * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
142 * listxattr, getxattr and setxattr with an extra options argument
143 * which mimics the l variants of the functions when we specify
144 * XATTR_NOFOLLOW as the options value.
146 #if defined(HAVE_DARWIN_OS)
147 #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
148 #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
149 #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
152 * Fallback to the non l-functions when those are not available.
154 #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
155 #define lgetxattr getxattr
157 #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
158 #define lsetxattr setxattr
160 #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
161 #define llistxattr listxattr
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 * The xattr stream for OSX, FreeBSD, Linux and NetBSD is a serialized stream of bytes
195 * which encodes one or more xattr_t structures.
197 * The Serialized stream consists of the following elements:
198 * magic - A magic string which makes it easy to detect any binary incompatabilites
199 * name_length - The length of the following xattr name
200 * name - The name of the extended attribute
201 * value_length - The length of the following xattr data
202 * value - The actual content of the extended attribute
204 * This is repeated 1 or more times.
207 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
209 xattr_t *current_xattr;
213 * Make sure the serialized stream fits in the poolmem buffer.
214 * We allocate some more to be sure the stream is gonna fit.
216 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
217 ser_begin(jcr->xattr_data, expected_serialize_len + 10);
220 * Walk the list of xattrs and serialize the data.
222 for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
224 * See if we can shortcut.
226 if (current_xattr->magic != XATTR_MAGIC)
229 ser_uint32(current_xattr->magic);
230 ser_uint32(current_xattr->name_length);
231 ser_bytes(current_xattr->name, current_xattr->name_length);
233 ser_uint32(current_xattr->value_length);
234 ser_bytes(current_xattr->value, current_xattr->value_length);
237 ser_end(jcr->xattr_data, expected_serialize_len + 10);
238 jcr->xattr_data_len = ser_length(jcr->xattr_data);
240 return jcr->xattr_data_len;
243 static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream)
246 int32_t xattr_list_len,
248 expected_serialize_len = 0;
249 char *xattr_list, *bp;
250 xattr_t *xattr_value_list, *current_xattr;
253 * First get the length of the available list with extended attributes.
255 xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
256 if (xattr_list_len < 0) {
258 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
259 jcr->last_fname, be.bstrerror());
260 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
261 jcr->last_fname, be.bstrerror());
263 } else if (xattr_list_len == 0) {
268 * Allocate room for the extented attribute list.
270 if ((xattr_list = (char *)malloc(xattr_list_len + 1)) == (char *)NULL) {
271 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_list_len + 1);
275 memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
278 * Get the actual list of extended attributes names for a file.
280 xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
281 if (xattr_list_len < 0) {
283 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
284 jcr->last_fname, be.bstrerror());
285 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
286 jcr->last_fname, be.bstrerror());
291 xattr_list[xattr_list_len] = '\0';
294 * Count the number of extended attributes on a file.
297 while ((bp - xattr_list) + 1 < xattr_list_len) {
300 bp = strchr(bp, '\0') + 1;
304 * Allocate enough room to hold all extended attributes.
305 * After allocating the storage make sure its empty by zeroing it.
307 if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
308 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
312 memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
315 * Walk the list of extended attributes names and retrieve the data.
316 * We already count the bytes needed for serializing the stream later on.
318 current_xattr = xattr_value_list;
320 while ((bp - xattr_list) + 1 < xattr_list_len) {
321 #if defined(HAVE_LINUX_OS)
323 * On Linux you also get the acls in the extented attribute list.
324 * So we check if we are already backing up acls and if we do we
325 * don't store the extended attribute with the same info.
327 if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
328 bp = strchr(bp, '\0') + 1;
335 * Each xattr valuepair starts with a magic so we can parse it easier.
337 current_xattr->magic = XATTR_MAGIC;
338 expected_serialize_len += sizeof(current_xattr->magic);
341 * Allocate space for storing the name.
343 current_xattr->name_length = strlen(bp);
344 if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
345 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
349 memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
351 expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
354 * First see how long the value is for the extended attribute.
356 xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
357 if (xattr_value_len < 0) {
359 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
360 jcr->last_fname, be.bstrerror());
361 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
362 jcr->last_fname, be.bstrerror());
368 * Allocate space for storing the value.
370 if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
371 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
375 memset((caddr_t)current_xattr->value, 0, xattr_value_len);
377 xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
378 if (xattr_value_len < 0) {
380 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
381 jcr->last_fname, be.bstrerror());
382 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
383 jcr->last_fname, be.bstrerror());
389 * Store the actual length of the value.
391 current_xattr->value_length = xattr_value_len;
392 expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
395 * Protect ourself against things getting out of hand.
397 if (expected_serialize_len >= MAX_XATTR_STREAM) {
398 Jmsg2(jcr, M_ERROR, 0, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
399 jcr->last_fname, MAX_XATTR_STREAM);
408 bp = strchr(bp, '\0') + 1;
412 * Serialize the datastream.
414 if (serialize_xattr_stream(jcr, expected_serialize_len, xattr_value_list) < expected_serialize_len) {
415 Jmsg1(jcr, M_ERROR, 0, _("Failed to serialize extended attributes on file \"%s\"\n"),
417 Dmsg1(100, "Failed to serialize extended attributes on file \"%s\"\n",
423 xattr_drop_internal_table(xattr_value_list);
427 * Send the datastream to the SD.
429 return send_xattr_stream(jcr, stream);
432 xattr_drop_internal_table(xattr_value_list);
438 static bool generic_xattr_parse_streams(JCR *jcr)
441 xattr_t current_xattr;
445 * Parse the stream and perform the setxattr calls on the file.
447 * Start unserializing the data. We keep on looping while we have not
448 * unserialized all bytes in the stream.
450 unser_begin(jcr->xattr_data, jcr->xattr_data_len);
451 while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
453 * First make sure the magic is present. This way we can easily catch corruption.
454 * Any missing MAGIC is fatal we do NOT try to continue.
456 unser_uint32(current_xattr.magic);
457 if (current_xattr.magic != XATTR_MAGIC) {
458 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
460 Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
467 * Decode the valuepair. First decode the length of the name.
469 unser_uint32(current_xattr.name_length);
472 * Allocate room for the name and decode its content.
474 if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
475 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
479 unser_bytes(current_xattr.name, current_xattr.name_length);
482 * The xattr_name needs to be null terminated for lsetxattr.
484 current_xattr.name[current_xattr.name_length] = '\0';
487 * Decode the value length.
489 unser_uint32(current_xattr.value_length);
492 * Allocate room for the value and decode its content.
494 if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
495 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
499 unser_bytes(current_xattr.value, current_xattr.value_length);
502 * Try to set the extended attribute on the file.
503 * If we fail to set this attribute we flag the error but its not fatal,
504 * we try to restore the other extended attributes too.
506 if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
507 current_xattr.value_length, 0) != 0) {
509 Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
510 jcr->last_fname, be.bstrerror());
511 Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
512 jcr->last_fname, be.bstrerror());
515 * Reset the return flag to false to indicate one or more extended attributes
516 * could not be restored.
522 * Free the temporary buffers.
524 free(current_xattr.name);
525 free(current_xattr.value);
528 unser_end(jcr->xattr_data, jcr->xattr_data_len);
532 #if defined(HAVE_DARWIN_OS)
533 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
535 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
538 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
541 case STREAM_XATTR_DARWIN:
542 return generic_xattr_parse_streams(jcr);
547 #elif defined(HAVE_FREEBSD_OS)
548 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
550 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
553 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
556 case STREAM_XATTR_FREEBSD:
557 return generic_xattr_parse_streams(jcr);
562 #elif defined(HAVE_LINUX_OS)
563 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
565 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
568 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
571 case STREAM_XATTR_LINUX:
572 return generic_xattr_parse_streams(jcr);
577 #elif defined(HAVE_NETBSD_OS)
578 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
580 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
583 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
586 case STREAM_XATTR_NETBSD:
587 return generic_xattr_parse_streams(jcr);
593 #elif defined(HAVE_SUN_OS)
595 * Solaris extended attributes were introduced in Solaris 9
598 * Solaris extensible attributes were introduced in OpenSolaris
599 * by PSARC 2007/315 Solaris extensible attributes are also
600 * sometimes called extended system attributes.
602 * man fsattr(5) on Solaris gives a wealth of info. The most
603 * important bits are:
605 * Attributes are logically supported as files within the file
606 * system. The file system is therefore augmented with an
607 * orthogonal name space of file attributes. Any file (includ-
608 * ing attribute files) can have an arbitrarily deep attribute
609 * tree associated with it. Attribute values are accessed by
610 * file descriptors obtained through a special attribute inter-
611 * face. This logical view of "attributes as files" allows the
612 * leveraging of existing file system interface functionality
613 * to support the construction, deletion, and manipulation of
616 * The special files "." and ".." retain their accustomed
617 * semantics within the attribute hierarchy. The "." attribute
618 * file refers to the current directory and the ".." attribute
619 * file refers to the parent directory. The unnamed directory
620 * at the head of each attribute tree is considered the "child"
621 * of the file it is associated with and the ".." file refers
622 * to the associated file. For any non-directory file with
623 * attributes, the ".." entry in the unnamed directory refers
624 * to a file that is not a directory.
626 * Conceptually, the attribute model is fully general. Extended
627 * attributes can be any type of file (doors, links, direc-
628 * tories, and so forth) and can even have their own attributes
629 * (fully recursive). As a result, the attributes associated
630 * with a file could be an arbitrarily deep directory hierarchy
631 * where each attribute could have an equally complex attribute
632 * tree associated with it. Not all implementations are able
633 * to, or want to, support the full model. Implementation are
634 * therefore permitted to reject operations that are not sup-
635 * ported. For example, the implementation for the UFS file
636 * system allows only regular files as attributes (for example,
637 * no sub-directories) and rejects attempts to place attributes
640 * The following list details the operations that are rejected
641 * in the current implementation:
643 * link Any attempt to create links between
644 * attribute and non-attribute space
645 * is rejected to prevent security-
646 * related or otherwise sensitive
647 * attributes from being exposed, and
648 * therefore manipulable, as regular
651 * rename Any attempt to rename between
652 * attribute and non-attribute space
653 * is rejected to prevent an already
654 * linked file from being renamed and
655 * thereby circumventing the link res-
658 * mkdir, symlink, mknod Any attempt to create a "non-
659 * regular" file in attribute space is
660 * rejected to reduce the functional-
661 * ity, and therefore exposure and
662 * risk, of the initial implementa-
665 * The entire available name space has been allocated to "gen-
666 * eral use" to bring the implementation in line with the NFSv4
667 * draft standard [NFSv4]. That standard defines "named attri-
668 * butes" (equivalent to Solaris Extended Attributes) with no
669 * naming restrictions. All Sun applications making use of
670 * opaque extended attributes will use the prefix "SUNW".
673 #ifdef HAVE_SYS_ATTR_H
674 #include <sys/attr.h>
681 #ifdef HAVE_SYS_NVPAIR_H
682 #include <sys/nvpair.h>
685 #ifdef HAVE_SYS_ACL_H
690 * This is the count of xattrs saved on a certain file, it gets reset
691 * on each new file processed and is used to see if we need to send
692 * the hidden xattr dir data. We only send that data when we encounter
693 * an other xattr on the file.
695 static int nr_xattr_saved = 0;
696 static char toplevel_hidden_dir_xattr_data[MAXSTRING];
697 static int toplevel_hidden_dir_xattr_data_len;
700 * This code creates a temporary cache with entries for each xattr which has
701 * a link count > 1 (which indicates it has one or more hard linked counterpart(s))
703 static xattr_link_cache_entry_t *xattr_link_cache_head = NULL,
704 *xattr_link_cache_tail = NULL;
706 static struct xattr_link_cache_entry *find_xattr_link_cache_entry(ino_t inum)
708 xattr_link_cache_entry_t *ptr;
710 for (ptr = xattr_link_cache_head; ptr != NULL; ptr = ptr->next)
711 if (ptr->inum == inum)
717 static void add_xattr_link_cache_entry(ino_t inum, char *target)
719 xattr_link_cache_entry_t *ptr;
721 if ((ptr = (xattr_link_cache_entry_t *)malloc(sizeof(struct xattr_link_cache_entry))) != NULL) {
722 memset((caddr_t)ptr, 0, sizeof(struct xattr_link_cache_entry));
724 strncpy(ptr->target, target, sizeof(ptr->target));
725 if (xattr_link_cache_head == NULL)
726 xattr_link_cache_head = ptr;
727 xattr_link_cache_tail = ptr;
731 static void drop_xattr_link_cache(void)
733 xattr_link_cache_entry_t *ptr, *next;
735 for (ptr = xattr_link_cache_tail; ptr != NULL; ptr = next) {
740 xattr_link_cache_head = NULL;
741 xattr_link_cache_tail = NULL;
744 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
746 * This function returns true if a non default extended system attribute
747 * list is associated with fd and returns false when an error has occured
748 * or when only extended system attributes other than archive,
749 * av_modified or crtime are set.
751 * The function returns true for the following cases:
753 * - any extended system attribute other than the default attributes
754 * ('archive', 'av_modified' and 'crtime') is set
755 * - nvlist has NULL name string
756 * - nvpair has data type of 'nvlist'
757 * - default data type.
759 static bool solaris_has_non_transient_extensible_attributes(int fd)
769 if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
774 while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
775 name = nvpair_name(pair);
778 fattr = name_to_attr(name);
784 type = nvpair_type(pair);
786 case DATA_TYPE_BOOLEAN_VALUE:
787 if (nvpair_value_boolean_value(pair, &value) != 0) {
790 if (value && fattr != F_ARCHIVE &&
791 fattr != F_AV_MODIFIED) {
796 case DATA_TYPE_UINT64_ARRAY:
797 if (fattr != F_CRTIME) {
802 case DATA_TYPE_NVLIST:
810 if (response != NULL)
811 nvlist_free(response);
815 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
817 #if defined(HAVE_ACL) && !defined(HAVE_EXTENDED_ACL)
819 * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
820 * There is no need to store those acls as we already store the stat bits too.
822 static bool acl_is_trivial(int count, aclent_t *entries)
827 for (n = 0; n < count; n++) {
830 if (!(ace->a_type == USER_OBJ ||
831 ace->a_type == GROUP_OBJ ||
832 ace->a_type == OTHER_OBJ ||
833 ace->a_type == CLASS_OBJ))
839 #endif /* HAVE_ACL && !HAVE_EXTENDED_ACL */
841 static bool solaris_archive_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text)
844 #ifdef HAVE_EXTENDED_ACL
849 * See if this attribute has an ACL
851 if ((fd != -1 && fpathconf(fd, _PC_ACL_ENABLED) > 0) ||
852 pathconf(attrname, _PC_ACL_ENABLED) > 0) {
854 * See if there is a non trivial acl on the file.
856 if ((fd != -1 && facl_get(fd, ACL_NO_TRIVIAL, &aclp) != 0) ||
857 acl_get(attrname, ACL_NO_TRIVIAL, &aclp) != 0) {
859 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
860 attrname, jcr->last_fname, be.bstrerror());
861 Dmsg3(100, "facl_get/acl_get of xattr %s on \"%s\" failed: ERR=%s\n",
862 attrname, jcr->last_fname, be.bstrerror());
868 #if defined(ACL_SID_FMT)
870 * New format flag added in newer Solaris versions.
872 flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
874 flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
875 #endif /* ACL_SID_FMT */
877 *acl_text = acl_totext(aclp, flags);
887 #else /* HAVE_EXTENDED_ACL */
889 aclent_t *acls = NULL;
892 * See if this attribute has an ACL
895 n = facl(fd, GETACLCNT, 0, NULL);
897 n = acl(attrname, GETACLCNT, 0, NULL);
899 if (n >= MIN_ACL_ENTRIES) {
900 acls = (aclent_t *)malloc(n * sizeof(aclent_t));
901 if ((fd != -1 && facl(fd, GETACL, n, acls) != n) ||
902 acl(attrname, GETACL, n, acls) != n) {
904 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
905 attrname, jcr->last_fname, be.bstrerror());
906 Dmsg3(100, "facl/acl of xattr %s on \"%s\" failed: ERR=%s\n",
907 attrname, jcr->last_fname, be.bstrerror());
914 * See if there is a non trivial acl on the file.
916 if (!acl_is_trivial(n, acls)) {
917 if ((*acl_text = acltotext(acls, n)) == NULL) {
919 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl text on xattr %s on file \"%s\": ERR=%s\n"),
920 attrname, jcr->last_fname, be.bstrerror());
921 Dmsg3(100, "acltotext of xattr %s on \"%s\" failed: ERR=%s\n",
922 attrname, jcr->last_fname, be.bstrerror());
937 #endif /* HAVE_EXTENDED_ACL */
940 #endif /* HAVE_ACL */
944 * Forward declaration for recursive function call.
946 static bool solaris_archive_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent);
949 * Archive an extended or extensible attribute.
950 * This is stored as an opaque stream of bytes with the following encoding:
952 * <xattr_name>\0<stat_buffer>\0<acl_string>\0<actual_xattr_data>
954 * or for a hardlinked or symlinked attribute
956 * <xattr_name>\0<stat_buffer>\0<xattr_link_source>\0
958 * xattr_name can be a subpath relative to the file the xattr is on.
959 * stat_buffer is the string representation of the stat struct.
960 * acl_string is an acl text when a non trivial acl is set on the xattr.
961 * actual_xattr_data is the content of the xattr file.
963 static bool solaris_archive_xattr(JCR *jcr, int fd, const char *xattr_namespace,
964 const char *attrname, bool toplevel_hidden_dir, int stream)
969 struct xattr_link_cache_entry *xlce;
970 char target_attrname[PATH_MAX];
971 char link_source[PATH_MAX];
972 char *acl_text = NULL;
973 char attribs[MAXSTRING];
977 snprintf(target_attrname, sizeof(target_attrname), "%s%s", xattr_namespace, attrname);
980 * Get the stats of the extended or extensible attribute.
982 if (fstatat(fd, attrname, &st, AT_SYMLINK_NOFOLLOW) < 0) {
984 Jmsg3(jcr, M_ERROR, 0, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"),
985 target_attrname, jcr->last_fname, be.bstrerror());
986 Dmsg3(100, "fstatat of xattr %s on \"%s\" failed: ERR=%s\n",
987 target_attrname, jcr->last_fname, be.bstrerror());
993 * Based on the filetype perform the correct action. We support most filetypes here, more
994 * then the actual implementation on Solaris supports so some code may never get executed
995 * due to limitations in the implementation.
997 switch (st.st_mode & S_IFMT) {
1002 * Get any acl on the xattr.
1004 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1008 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1009 * Encode the stat struct into an ASCII representation.
1011 encode_stat(attribs, &st, 0, stream);
1012 cnt = snprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c",
1013 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1017 * Get any acl on the xattr.
1019 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1023 * See if this is the toplevel_hidden_dir being archived.
1025 if (toplevel_hidden_dir) {
1027 * Save the data for later storage when we encounter a real xattr.
1028 * Encode the stat struct into an ASCII representation and jump out of the function.
1030 encode_stat(attribs, &st, 0, stream);
1031 toplevel_hidden_dir_xattr_data_len = snprintf(toplevel_hidden_dir_xattr_data,
1032 sizeof(toplevel_hidden_dir_xattr_data),
1034 target_attrname, 0, attribs, 0,
1035 (acl_text) ? acl_text : "", 0);
1040 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1041 * Encode the stat struct into an ASCII representation.
1043 encode_stat(attribs, &st, 0, stream);
1044 cnt = snprintf(buffer, sizeof(buffer),
1046 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1051 * If this is a hardlinked file check the inode cache for a hit.
1053 if (st.st_nlink > 1) {
1055 * See if the cache already knows this inode number.
1057 if ((xlce = find_xattr_link_cache_entry(st.st_ino)) != NULL) {
1059 * Generate a xattr encoding with the reference to the target in there.
1061 encode_stat(attribs, &st, st.st_ino, stream);
1062 cnt = snprintf(buffer, sizeof(buffer),
1064 target_attrname, 0, attribs, 0, xlce->target, 0);
1065 pm_memcpy(jcr->xattr_data, buffer, cnt);
1066 jcr->xattr_data_len = cnt;
1067 retval = send_xattr_stream(jcr, stream);
1070 * For a hard linked file we are ready now, no need to recursively archive the attributes.
1076 * Store this hard linked file in the cache.
1077 * Store the name relative to the top level xattr space.
1079 add_xattr_link_cache_entry(st.st_ino, target_attrname + 1);
1083 * Get any acl on the xattr.
1085 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1089 * Encode the stat struct into an ASCII representation.
1091 encode_stat(attribs, &st, 0, stream);
1092 cnt = snprintf(buffer, sizeof(buffer),
1094 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1097 * Open the extended or extensible attribute file.
1099 if ((attrfd = openat(fd, attrname, O_RDONLY)) < 0) {
1101 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on \"%s\": ERR=%s\n"),
1102 target_attrname, jcr->last_fname, be.bstrerror());
1103 Dmsg3(100, "openat of xattr %s on \"%s\" failed: ERR=%s\n",
1104 target_attrname, jcr->last_fname, be.bstrerror());
1111 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1112 * Encode the stat struct into an ASCII representation.
1114 if (readlink(attrname, link_source, sizeof(link_source)) < 0) {
1116 Jmsg3(jcr, M_ERROR, 0, _("Unable to read symlin %s on \"%s\": ERR=%s\n"),
1117 target_attrname, jcr->last_fname, be.bstrerror());
1118 Dmsg3(100, "readlink of xattr %s on \"%s\" failed: ERR=%s\n",
1119 target_attrname, jcr->last_fname, be.bstrerror());
1125 * Generate a xattr encoding with the reference to the target in there.
1127 encode_stat(attribs, &st, st.st_ino, stream);
1128 cnt = snprintf(buffer, sizeof(buffer),
1130 target_attrname, 0, attribs, 0, link_source, 0);
1131 pm_memcpy(jcr->xattr_data, buffer, cnt);
1132 jcr->xattr_data_len = cnt;
1133 retval = send_xattr_stream(jcr, stream);
1136 * For a soft linked file we are ready now, no need to recursively archive the attributes.
1144 * See if this is the first real xattr being saved. If it is save the toplevel_hidden_dir attributes first.
1146 if (nr_xattr_saved == 0) {
1147 pm_memcpy(jcr->xattr_data, toplevel_hidden_dir_xattr_data, toplevel_hidden_dir_xattr_data_len);
1148 jcr->xattr_data_len = toplevel_hidden_dir_xattr_data_len;
1149 send_xattr_stream(jcr, STREAM_XATTR_SOLARIS);
1152 pm_memcpy(jcr->xattr_data, buffer, cnt);
1153 jcr->xattr_data_len = cnt;
1156 * Only dump the content of regular files.
1158 switch (st.st_mode & S_IFMT) {
1160 if (st.st_size > 0) {
1162 * Protect ourself against things getting out of hand.
1164 if (st.st_size >= MAX_XATTR_STREAM) {
1165 Jmsg2(jcr, M_ERROR, 0, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
1166 jcr->last_fname, MAX_XATTR_STREAM);
1171 while ((cnt = read(attrfd, buffer, sizeof(buffer))) > 0) {
1172 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, jcr->xattr_data_len + cnt);
1173 memcpy(jcr->xattr_data + jcr->xattr_data_len, buffer, cnt);
1174 jcr->xattr_data_len += cnt;
1178 Jmsg2(jcr, M_ERROR, 0, _("Unable to read content of xattr %s on file \"%s\"\n"),
1179 target_attrname, jcr->last_fname);
1180 Dmsg2(100, "read of data from xattr %s on \"%s\" failed\n",
1181 target_attrname, jcr->last_fname);
1191 retval = send_xattr_stream(jcr, stream);
1195 * Recursivly call solaris_archive_extended_attributes for archiving the attributes
1196 * available on this extended attribute.
1199 retval = solaris_archive_xattrs(jcr, xattr_namespace, attrname);
1202 * The recursive call could change our working dir so change back to the wanted workdir.
1204 if (fchdir(fd) < 0) {
1206 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"),
1207 jcr->last_fname, be.bstrerror());
1208 Dmsg3(100, "Unable to fchdir to xattr space of file \"%s\" using fd %d: ERR=%s\n",
1209 jcr->last_fname, fd, be.bstrerror());
1224 static bool solaris_archive_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent)
1227 int fd, filefd = -1, attrdirfd = -1;
1230 char current_xattr_namespace[PATH_MAX];
1231 bool retval = false;
1234 * Determine what argument to use. Use attr_parent when set
1235 * (recursive call) or jcr->last_fname for first call. Also save
1236 * the current depth of the xattr_space we are in.
1240 if (xattr_namespace)
1241 snprintf(current_xattr_namespace, sizeof(current_xattr_namespace), "%s%s/",
1242 xattr_namespace, attr_parent);
1244 strcpy(current_xattr_namespace, "/");
1246 name = jcr->last_fname;
1247 strcpy(current_xattr_namespace, "/");
1251 * Open the file on which to archive the xattrs read-only.
1253 if ((filefd = open(name, O_RDONLY | O_NONBLOCK)) < 0) {
1255 Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"),
1256 jcr->last_fname, be.bstrerror());
1257 Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1258 jcr->last_fname, be.bstrerror());
1264 * Open the xattr naming space.
1266 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1270 * Gentile way of the system saying this type of xattr layering is not supported.
1271 * Which is not problem we just forget about this this xattr.
1272 * But as this is not an error we return a positive return value.
1278 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1279 name, jcr->last_fname, be.bstrerror());
1280 Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1281 name, jcr->last_fname, be.bstrerror());
1288 * We need to change into the attribute directory to determine if each of the
1289 * attributes should be archived.
1291 if (fchdir(attrdirfd) < 0) {
1293 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1294 jcr->last_fname, be.bstrerror());
1295 Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1296 jcr->last_fname, attrdirfd, be.bstrerror());
1302 * Save the data of the toplevel xattr hidden_dir. We save this one before anything
1303 * else because the readdir returns "." entry after the extensible attr entry.
1304 * And as we want this entry before anything else we better just save its data.
1307 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, ".",
1308 true, STREAM_XATTR_SOLARIS);
1310 if ((fd = dup(attrdirfd)) == -1 ||
1311 (dirp = fdopendir(fd)) == (DIR *)NULL) {
1313 Jmsg2(jcr, M_ERROR, 0, _("Unable to list the xattr space on file \"%s\": ERR=%s\n"),
1314 jcr->last_fname, be.bstrerror());
1315 Dmsg3(100, "Unable to fdopendir xattr space on file \"%s\" using fd %d: ERR=%s\n",
1316 jcr->last_fname, fd, be.bstrerror());
1322 * Walk the namespace.
1324 while (dp = readdir(dirp)) {
1326 * Skip only the toplevel . dir.
1328 if (!attr_parent && !strcmp(dp->d_name, "."))
1332 * Skip all .. directories
1334 if (!strcmp(dp->d_name, ".."))
1337 Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
1338 current_xattr_namespace, dp->d_name, jcr->last_fname);
1340 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1342 * We are not interested in read-only extensible attributes.
1344 if (!strcmp(dp->d_name, VIEW_READONLY)) {
1345 Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
1346 current_xattr_namespace, dp->d_name, jcr->last_fname);
1352 * We are only interested in read-write extensible attributes
1353 * when they contain non-transient values.
1355 if (!strcmp(dp->d_name, VIEW_READWRITE)) {
1357 * Determine if there are non-transient system attributes at the toplevel.
1358 * We need to provide a fd to the open file.
1360 if (!solaris_has_non_transient_extensible_attributes(filefd)) {
1361 Dmsg3(400, "Skipping transient extensible attributes %s%s on file \"%s\"\n",
1362 current_xattr_namespace, dp->d_name, jcr->last_fname);
1368 * Archive the xattr.
1370 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1371 false, STREAM_XATTR_SOLARIS_SYS);
1374 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
1377 * Archive the xattr.
1379 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1380 false, STREAM_XATTR_SOLARIS);
1387 if (attrdirfd != -1)
1396 static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, char *acl_text)
1398 #ifdef HAVE_EXTENDED_ACL
1402 if ((error = acl_fromtext(acl_text, &aclp)) != 0) {
1406 if ((fd != -1 && facl_set(fd, aclp) != 0) ||
1407 acl_set(attrname, aclp) != 0) {
1409 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1410 attrname, jcr->last_fname, be.bstrerror());
1411 Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1412 attrname, jcr->last_fname, be.bstrerror());
1421 #else /* HAVE_EXTENDED_ACL */
1423 aclent_t *acls = NULL;
1425 acls = aclfromtext(acl_text, &n);
1427 if ((fd != -1 && facl(fd, SETACL, n, acls) != 0) ||
1428 acl(attrname, SETACL, n, acls) != 0) {
1430 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1431 attrname, jcr->last_fname, be.bstrerror());
1432 Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1433 attrname, jcr->last_fname, be.bstrerror());
1443 #endif /* HAVE_EXTENDED_ACL */
1445 #endif /* HAVE_ACL */
1447 static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible)
1449 int fd, filefd = -1, attrdirfd = -1, attrfd = -1;
1450 int used_bytes, total_bytes, cnt;
1451 char *bp, *target_attrname, *attribs;
1452 char *linked_target = NULL;
1453 char *acl_text = NULL;
1457 struct timeval times[2];
1458 bool retval = false;
1461 * Parse the xattr stream. First the part that is the same for all xattrs.
1464 total_bytes = jcr->xattr_data_len;
1467 * The name of the target xattr has a leading / we are not interested
1468 * in that so skip it when decoding the string. We always start a the /
1469 * of the xattr space anyway.
1471 target_attrname = jcr->xattr_data + 1;
1472 if ((bp = strchr(target_attrname, '\0')) == (char *)NULL ||
1473 (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
1479 * Open the file on which to restore the xattrs read-only.
1481 if ((filefd = open(jcr->last_fname, O_RDONLY | O_NONBLOCK)) < 0) {
1483 Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"),
1484 jcr->last_fname, be.bstrerror());
1485 Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1486 jcr->last_fname, be.bstrerror());
1492 * Open the xattr naming space and make it the current working dir.
1494 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1496 Jmsg2(jcr, M_ERROR, 0, _("Unable to open xattr space on file \"%s\": ERR=%s\n"),
1497 jcr->last_fname, be.bstrerror());
1498 Dmsg2(100, "Unable to open xattr space on file \"%s\": ERR=%s\n",
1499 jcr->last_fname, be.bstrerror());
1504 if (fchdir(attrdirfd) < 0) {
1506 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1507 jcr->last_fname, be.bstrerror());
1508 Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1509 jcr->last_fname, attrdirfd, be.bstrerror());
1515 * Try to open the correct xattr subdir based on the target_attrname given.
1516 * e.g. check if its a subdir attrname. Each / in the string makes us go
1519 while ((bp = strchr(target_attrname, '/')) != (char *)NULL) {
1522 if ((fd = open(target_attrname, O_RDONLY | O_NONBLOCK)) < 0) {
1524 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1525 target_attrname, jcr->last_fname, be.bstrerror());
1526 Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1527 target_attrname, jcr->last_fname, be.bstrerror());
1536 * Open the xattr naming space.
1538 if ((fd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1540 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1541 target_attrname, jcr->last_fname, be.bstrerror());
1542 Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1543 target_attrname, jcr->last_fname, be.bstrerror());
1552 * Make the xattr space our current workingdir.
1554 if (fchdir(attrdirfd) < 0) {
1556 Jmsg3(jcr, M_ERROR, 0, _("Unable to chdir to xattr space %s on file \"%s\": ERR=%s\n"),
1557 target_attrname, jcr->last_fname, be.bstrerror());
1558 Dmsg4(100, "Unable to fchdir to xattr space %s on file \"%s\" using fd %d: ERR=%s\n",
1559 target_attrname, jcr->last_fname, attrdirfd, be.bstrerror());
1564 target_attrname = ++bp;
1568 * Decode the attributes from the stream.
1570 decode_stat(attribs, &st, &inum);
1573 * Decode the next field (acl_text).
1575 if ((bp = strchr(attribs, '\0')) == (char *)NULL ||
1576 (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
1582 * Based on the filetype perform the correct action. We support most filetypes here, more
1583 * then the actual implementation on Solaris supports so some code may never get executed
1584 * due to limitations in the implementation.
1586 switch (st.st_mode & S_IFMT) {
1589 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1591 unlinkat(attrdirfd, target_attrname, 0);
1592 if (mkfifo(target_attrname, st.st_mode) < 0) {
1594 Jmsg3(jcr, M_ERROR, 0, _("Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n"),
1595 target_attrname, jcr->last_fname, be.bstrerror());
1596 Dmsg3(100, "Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n",
1597 target_attrname, jcr->last_fname, be.bstrerror());
1605 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1607 unlinkat(attrdirfd, target_attrname, 0);
1608 if (mknod(target_attrname, st.st_mode, st.st_rdev) < 0) {
1610 Jmsg3(jcr, M_ERROR, 0, _("Unable to mknod xattr %s on file \"%s\": ERR=%s\n"),
1611 target_attrname, jcr->last_fname, be.bstrerror());
1612 Dmsg3(100, "Unable to mknod xattr %s on file \"%s\": ERR=%s\n",
1613 target_attrname, jcr->last_fname, be.bstrerror());
1620 * If its not the hidden_dir create the entry.
1621 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1623 if (strcmp(target_attrname, ".")) {
1624 unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
1625 if (mkdir(target_attrname, st.st_mode) < 0) {
1627 Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
1628 target_attrname, jcr->last_fname, be.bstrerror());
1629 Dmsg3(100, "Unable to mkdir xattr %s on file \"%s\": ERR=%s\n",
1630 target_attrname, jcr->last_fname, be.bstrerror());
1638 * See if this is a hard linked file. e.g. inum != 0
1643 unlinkat(attrdirfd, target_attrname, 0);
1644 if (link(linked_target, target_attrname) < 0) {
1646 Jmsg4(jcr, M_ERROR, 0, _("Unable to link xattr %s to %s on file \"%s\": ERR=%s\n"),
1647 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1648 Dmsg4(100, "Unable to link xattr %s to %s on file \"%s\": ERR=%s\n",
1649 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1655 * Successfully restored xattr.
1660 if ((bp = strchr(acl_text, '\0')) == (char *)NULL ||
1661 (used_bytes = (bp - jcr->xattr_data)) >= total_bytes) {
1665 if (used_bytes < (total_bytes - 1))
1669 * Restore the actual xattr.
1671 if (!is_extensible) {
1672 unlinkat(attrdirfd, target_attrname, 0);
1675 if ((attrfd = openat(attrdirfd, target_attrname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) {
1677 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1678 target_attrname, jcr->last_fname, be.bstrerror());
1679 Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1680 target_attrname, jcr->last_fname, be.bstrerror());
1687 * Restore the actual data.
1689 if (st.st_size > 0) {
1690 used_bytes = (data - jcr->xattr_data);
1691 cnt = total_bytes - used_bytes;
1694 * Do a sanity check, the st.st_size should be the same as the number of bytes
1695 * we have available as data of the stream.
1697 if (cnt != st.st_size) {
1698 Jmsg2(jcr, M_ERROR, 0, _("Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n"),
1699 target_attrname, jcr->last_fname);
1700 Dmsg2(100, "Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n",
1701 target_attrname, jcr->last_fname);
1707 cnt = write(attrfd, data, cnt);
1710 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore data of xattr %s on file \"%s\": ERR=%s\n"),
1711 target_attrname, jcr->last_fname, be.bstrerror());
1712 Dmsg3(100, "Unable to restore data of xattr %s on file \"%s\": ERR=%s\n",
1713 target_attrname, jcr->last_fname, be.bstrerror());
1720 cnt = total_bytes - used_bytes;
1726 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1730 if (symlink(linked_target, target_attrname) < 0) {
1732 Jmsg4(jcr, M_ERROR, 0, _("Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n"),
1733 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1734 Dmsg4(100, "Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n",
1735 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1741 * Successfully restored xattr.
1750 * Restore owner and acl for non extensible attributes.
1752 if (!is_extensible) {
1753 if (fchownat(attrdirfd, target_attrname, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW) < 0) {
1757 * Gentile way of the system saying this type of xattr layering is not supported.
1758 * But as this is not an error we return a positive return value.
1764 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n"),
1765 target_attrname, jcr->last_fname, be.bstrerror());
1766 Dmsg3(100, "Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n",
1767 target_attrname, jcr->last_fname, be.bstrerror());
1775 if (acl_text && *acl_text)
1776 if (!solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text))
1778 #endif /* HAVE_ACL */
1781 * For a non extensible attribute restore access and modification time on the xattr.
1783 if (!is_extensible) {
1784 times[0].tv_sec = st.st_atime;
1785 times[0].tv_usec = 0;
1786 times[1].tv_sec = st.st_mtime;
1787 times[1].tv_usec = 0;
1789 if (futimesat(attrdirfd, target_attrname, times) < 0) {
1791 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n"),
1792 target_attrname, jcr->last_fname, be.bstrerror());
1793 Dmsg3(100, "Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n",
1794 target_attrname, jcr->last_fname, be.bstrerror());
1801 * Successfully restored xattr.
1807 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n"),
1809 Dmsg1(100, "Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n",
1815 if (attrdirfd != -1)
1823 static bool solaris_extract_xattr(JCR *jcr, int stream)
1826 bool is_extensible = false;
1830 * First make sure we can restore xattr on the filesystem.
1833 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1834 case STREAM_XATTR_SOLARIS_SYS:
1835 if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
1836 Qmsg1(jcr, M_WARNING, 0,
1837 _("Failed to restore extensible attributes on file \"%s\"\n"),
1839 Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n",
1845 is_extensible = true;
1848 case STREAM_XATTR_SOLARIS:
1849 if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
1850 Qmsg1(jcr, M_WARNING, 0,
1851 _("Failed to restore extended attributes on file \"%s\"\n"),
1853 Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n",
1865 * As we change the cwd in the restore function save the current cwd
1866 * for restore after return from the solaris_restore_xattrs function.
1868 getcwd(cwd, sizeof(cwd));
1869 retval = solaris_restore_xattrs(jcr, is_extensible);
1875 static int solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1881 * First see if extended attributes or extensible attributes are present.
1882 * If not just pretend things went ok.
1884 if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) {
1888 * As we change the cwd in the archive function save the current cwd
1889 * for restore after return from the solaris_archive_xattrs function.
1891 getcwd(cwd, sizeof(cwd));
1892 retval = solaris_archive_xattrs(jcr, NULL, NULL);
1895 drop_xattr_link_cache();
1901 static bool solaris_parse_xattr_stream(JCR *jcr, int stream)
1904 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1905 case STREAM_XATTR_SOLARIS_SYS:
1907 case STREAM_XATTR_SOLARIS:
1908 return solaris_extract_xattr(jcr, stream);
1915 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1917 #if defined(HAVE_SUN_OS)
1918 return solaris_build_xattr_streams(jcr, ff_pkt);
1919 #elif defined(HAVE_DARWIN_OS)
1920 return darwin_build_xattr_streams(jcr, ff_pkt);
1921 #elif defined(HAVE_FREEBSD_OS)
1922 return freebsd_build_xattr_streams(jcr, ff_pkt);
1923 #elif defined(HAVE_LINUX_OS)
1924 return linux_build_xattr_streams(jcr, ff_pkt);
1925 #elif defined(HAVE_NETBSD_OS)
1926 return netbsd_build_xattr_streams(jcr, ff_pkt);
1930 bool parse_xattr_stream(JCR *jcr, int stream)
1933 * Based on the stream being passed in dispatch to the right function
1934 * for parsing and restoring a specific xattr. The platform determines
1935 * which streams are recognized and parsed and which are handled by
1936 * the default case and ignored. As only one of the platform defines
1937 * is true per compile we never end up with duplicate switch values.
1940 #if defined(HAVE_SUN_OS)
1941 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1942 case STREAM_XATTR_SOLARIS_SYS:
1944 case STREAM_XATTR_SOLARIS:
1945 return solaris_parse_xattr_stream(jcr, stream);
1946 #elif defined(HAVE_DARWIN_OS)
1947 case STREAM_XATTR_DARWIN:
1948 return darwin_parse_xattr_stream(jcr, stream);
1949 #elif defined(HAVE_FREEBSD_OS)
1950 case STREAM_XATTR_FREEBSD:
1951 return freebsd_parse_xattr_stream(jcr, stream);
1952 #elif defined(HAVE_LINUX_OS)
1953 case STREAM_XATTR_LINUX:
1954 return linux_parse_xattr_stream(jcr, stream);
1955 #elif defined(HAVE_NETBSD_OS)
1956 case STREAM_XATTR_NETBSD:
1957 return netbsd_parse_xattr_stream(jcr, stream);
1961 * Issue a warning and discard the message. But pretend the restore was ok.
1963 Qmsg2(jcr, M_WARNING, 0,
1964 _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
1965 jcr->last_fname, stream);
1967 } /* end switch (stream) */