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
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 (jcr->xattr_data_len <= 0)
96 if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
97 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
104 * Send the buffer to the storage deamon
106 Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
108 sd->msg = jcr->xattr_data;
109 sd->msglen = jcr->xattr_data_len;
113 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
119 jcr->JobBytes += sd->msglen;
121 if (!sd->signal(BNET_EOD)) {
122 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
128 Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
134 * This is a supported OS, See what kind of interface we should use.
135 * Start with the generic interface used by most OS-es.
137 #if defined(HAVE_DARWIN_OS) \
138 || defined(HAVE_FREEBSD_OS) \
139 || defined(HAVE_LINUX_OS) \
140 || defined(HAVE_NETBSD_OS)
142 #ifdef HAVE_SYS_XATTR_H
143 #include <sys/xattr.h>
147 * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
148 * listxattr, getxattr and setxattr with an extra options argument
149 * which mimics the l variants of the functions when we specify
150 * XATTR_NOFOLLOW as the options value.
152 #if defined(HAVE_DARWIN_OS)
153 #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
154 #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
155 #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
158 * Fallback to the non l-functions when those are not available.
160 #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
161 #define lgetxattr getxattr
163 #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
164 #define lsetxattr setxattr
166 #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
167 #define llistxattr listxattr
171 static void xattr_drop_internal_table(xattr_t *xattr_value_list)
173 xattr_t *current_xattr;
176 * Walk the list of xattrs and free allocated memory on traversing.
178 for (current_xattr = xattr_value_list;
179 current_xattr != (xattr_t *)NULL;
182 * See if we can shortcut.
184 if (current_xattr->magic != XATTR_MAGIC)
187 free(current_xattr->name);
189 if (current_xattr->value_length > 0)
190 free(current_xattr->value);
194 * Free the array of control structs.
196 free(xattr_value_list);
200 * The xattr stream for OSX, FreeBSD, Linux and NetBSD is a serialized stream of bytes
201 * which encodes one or more xattr_t structures.
203 * The Serialized stream consists of the following elements:
204 * magic - A magic string which makes it easy to detect any binary incompatabilites
205 * name_length - The length of the following xattr name
206 * name - The name of the extended attribute
207 * value_length - The length of the following xattr data
208 * value - The actual content of the extended attribute
210 * This is repeated 1 or more times.
213 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
215 xattr_t *current_xattr;
219 * Make sure the serialized stream fits in the poolmem buffer.
220 * We allocate some more to be sure the stream is gonna fit.
222 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
223 ser_begin(jcr->xattr_data, expected_serialize_len + 10);
226 * Walk the list of xattrs and serialize the data.
228 for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
230 * See if we can shortcut.
232 if (current_xattr->magic != XATTR_MAGIC)
235 ser_uint32(current_xattr->magic);
236 ser_uint32(current_xattr->name_length);
237 ser_bytes(current_xattr->name, current_xattr->name_length);
239 ser_uint32(current_xattr->value_length);
240 ser_bytes(current_xattr->value, current_xattr->value_length);
243 ser_end(jcr->xattr_data, expected_serialize_len + 10);
244 jcr->xattr_data_len = ser_length(jcr->xattr_data);
246 return jcr->xattr_data_len;
249 static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream)
252 int32_t xattr_list_len,
254 uint32_t expected_serialize_len = 0;
255 char *xattr_list, *bp;
256 xattr_t *xattr_value_list, *current_xattr;
259 * First get the length of the available list with extended attributes.
261 xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
262 if (xattr_list_len < 0) {
264 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
265 jcr->last_fname, be.bstrerror());
266 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
267 jcr->last_fname, be.bstrerror());
270 } else if (xattr_list_len == 0) {
275 * Allocate room for the extented attribute list.
277 if ((xattr_list = (char *)malloc(xattr_list_len + 1)) == (char *)NULL) {
278 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_list_len + 1);
282 memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
285 * Get the actual list of extended attributes names for a file.
287 xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
288 if (xattr_list_len < 0) {
290 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
291 jcr->last_fname, be.bstrerror());
292 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
293 jcr->last_fname, be.bstrerror());
299 xattr_list[xattr_list_len] = '\0';
302 * Count the number of extended attributes on a file.
305 while ((bp - xattr_list) + 1 < xattr_list_len) {
306 #if defined(HAVE_LINUX_OS)
308 * On Linux you also get the acls in the extented attribute list.
309 * So we check if we are already backing up acls and if we do we
310 * don't store the extended attribute with the same info.
312 if ((ff_pkt->flags & FO_ACL) == 0 || strcmp(bp, "system.posix_acl_access"))
318 bp = strchr(bp, '\0') + 1;
328 * Allocate enough room to hold all extended attributes.
329 * After allocating the storage make sure its empty by zeroing it.
331 if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
332 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
336 memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
339 * Walk the list of extended attributes names and retrieve the data.
340 * We already count the bytes needed for serializing the stream later on.
342 current_xattr = xattr_value_list;
344 while ((bp - xattr_list) + 1 < xattr_list_len) {
345 #if defined(HAVE_LINUX_OS)
346 if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
347 bp = strchr(bp, '\0') + 1;
354 * Each xattr valuepair starts with a magic so we can parse it easier.
356 current_xattr->magic = XATTR_MAGIC;
357 expected_serialize_len += sizeof(current_xattr->magic);
360 * Allocate space for storing the name.
362 current_xattr->name_length = strlen(bp);
363 if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
364 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
368 memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
370 expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
373 * First see how long the value is for the extended attribute.
375 xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
376 if (xattr_value_len < 0) {
378 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
379 jcr->last_fname, be.bstrerror());
380 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
381 jcr->last_fname, be.bstrerror());
387 * Allocate space for storing the value.
389 if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
390 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
394 memset((caddr_t)current_xattr->value, 0, xattr_value_len);
396 xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
397 if (xattr_value_len < 0) {
399 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
400 jcr->last_fname, be.bstrerror());
401 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
402 jcr->last_fname, be.bstrerror());
408 * Store the actual length of the value.
410 current_xattr->value_length = xattr_value_len;
411 expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
414 * Protect ourself against things getting out of hand.
416 if (expected_serialize_len >= MAX_XATTR_STREAM) {
417 Jmsg2(jcr, M_ERROR, 0, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
418 jcr->last_fname, MAX_XATTR_STREAM);
427 bp = strchr(bp, '\0') + 1;
431 * Serialize the datastream.
433 if (serialize_xattr_stream(jcr, expected_serialize_len, xattr_value_list) < expected_serialize_len) {
434 Jmsg1(jcr, M_ERROR, 0, _("Failed to serialize extended attributes on file \"%s\"\n"),
436 Dmsg1(100, "Failed to serialize extended attributes on file \"%s\"\n",
442 xattr_drop_internal_table(xattr_value_list);
446 * Send the datastream to the SD.
448 return send_xattr_stream(jcr, stream);
451 xattr_drop_internal_table(xattr_value_list);
457 static bool generic_xattr_parse_streams(JCR *jcr)
460 xattr_t current_xattr;
464 * Parse the stream and perform the setxattr calls on the file.
466 * Start unserializing the data. We keep on looping while we have not
467 * unserialized all bytes in the stream.
469 unser_begin(jcr->xattr_data, jcr->xattr_data_len);
470 while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
472 * First make sure the magic is present. This way we can easily catch corruption.
473 * Any missing MAGIC is fatal we do NOT try to continue.
475 unser_uint32(current_xattr.magic);
476 if (current_xattr.magic != XATTR_MAGIC) {
477 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
479 Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
486 * Decode the valuepair. First decode the length of the name.
488 unser_uint32(current_xattr.name_length);
491 * Allocate room for the name and decode its content.
493 if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
494 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
498 unser_bytes(current_xattr.name, current_xattr.name_length);
501 * The xattr_name needs to be null terminated for lsetxattr.
503 current_xattr.name[current_xattr.name_length] = '\0';
506 * Decode the value length.
508 unser_uint32(current_xattr.value_length);
511 * Allocate room for the value and decode its content.
513 if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
514 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
518 unser_bytes(current_xattr.value, current_xattr.value_length);
521 * Try to set the extended attribute on the file.
522 * If we fail to set this attribute we flag the error but its not fatal,
523 * we try to restore the other extended attributes too.
525 if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
526 current_xattr.value_length, 0) != 0) {
528 Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
529 jcr->last_fname, be.bstrerror());
530 Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
531 jcr->last_fname, be.bstrerror());
534 * Reset the return flag to false to indicate one or more extended attributes
535 * could not be restored.
541 * Free the temporary buffers.
543 free(current_xattr.name);
544 free(current_xattr.value);
547 unser_end(jcr->xattr_data, jcr->xattr_data_len);
551 #if defined(HAVE_DARWIN_OS)
552 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
554 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
557 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
560 case STREAM_XATTR_DARWIN:
561 return generic_xattr_parse_streams(jcr);
566 #elif defined(HAVE_FREEBSD_OS)
567 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
569 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
572 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
575 case STREAM_XATTR_FREEBSD:
576 return generic_xattr_parse_streams(jcr);
581 #elif defined(HAVE_LINUX_OS)
582 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
584 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
587 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
590 case STREAM_XATTR_LINUX:
591 return generic_xattr_parse_streams(jcr);
596 #elif defined(HAVE_NETBSD_OS)
597 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
599 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
602 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
605 case STREAM_XATTR_NETBSD:
606 return generic_xattr_parse_streams(jcr);
612 #elif defined(HAVE_SUN_OS)
614 * Solaris extended attributes were introduced in Solaris 9
617 * Solaris extensible attributes were introduced in OpenSolaris
618 * by PSARC 2007/315 Solaris extensible attributes are also
619 * sometimes called extended system attributes.
621 * man fsattr(5) on Solaris gives a wealth of info. The most
622 * important bits are:
624 * Attributes are logically supported as files within the file
625 * system. The file system is therefore augmented with an
626 * orthogonal name space of file attributes. Any file (includ-
627 * ing attribute files) can have an arbitrarily deep attribute
628 * tree associated with it. Attribute values are accessed by
629 * file descriptors obtained through a special attribute inter-
630 * face. This logical view of "attributes as files" allows the
631 * leveraging of existing file system interface functionality
632 * to support the construction, deletion, and manipulation of
635 * The special files "." and ".." retain their accustomed
636 * semantics within the attribute hierarchy. The "." attribute
637 * file refers to the current directory and the ".." attribute
638 * file refers to the parent directory. The unnamed directory
639 * at the head of each attribute tree is considered the "child"
640 * of the file it is associated with and the ".." file refers
641 * to the associated file. For any non-directory file with
642 * attributes, the ".." entry in the unnamed directory refers
643 * to a file that is not a directory.
645 * Conceptually, the attribute model is fully general. Extended
646 * attributes can be any type of file (doors, links, direc-
647 * tories, and so forth) and can even have their own attributes
648 * (fully recursive). As a result, the attributes associated
649 * with a file could be an arbitrarily deep directory hierarchy
650 * where each attribute could have an equally complex attribute
651 * tree associated with it. Not all implementations are able
652 * to, or want to, support the full model. Implementation are
653 * therefore permitted to reject operations that are not sup-
654 * ported. For example, the implementation for the UFS file
655 * system allows only regular files as attributes (for example,
656 * no sub-directories) and rejects attempts to place attributes
659 * The following list details the operations that are rejected
660 * in the current implementation:
662 * link Any attempt to create links between
663 * attribute and non-attribute space
664 * is rejected to prevent security-
665 * related or otherwise sensitive
666 * attributes from being exposed, and
667 * therefore manipulable, as regular
670 * rename Any attempt to rename between
671 * attribute and non-attribute space
672 * is rejected to prevent an already
673 * linked file from being renamed and
674 * thereby circumventing the link res-
677 * mkdir, symlink, mknod Any attempt to create a "non-
678 * regular" file in attribute space is
679 * rejected to reduce the functional-
680 * ity, and therefore exposure and
681 * risk, of the initial implementa-
684 * The entire available name space has been allocated to "gen-
685 * eral use" to bring the implementation in line with the NFSv4
686 * draft standard [NFSv4]. That standard defines "named attri-
687 * butes" (equivalent to Solaris Extended Attributes) with no
688 * naming restrictions. All Sun applications making use of
689 * opaque extended attributes will use the prefix "SUNW".
692 #ifdef HAVE_SYS_ATTR_H
693 #include <sys/attr.h>
700 #ifdef HAVE_SYS_NVPAIR_H
701 #include <sys/nvpair.h>
704 #ifdef HAVE_SYS_ACL_H
709 * This is the count of xattrs saved on a certain file, it gets reset
710 * on each new file processed and is used to see if we need to send
711 * the hidden xattr dir data. We only send that data when we encounter
712 * an other xattr on the file.
714 static int nr_xattr_saved = 0;
715 static char toplevel_hidden_dir_xattr_data[MAXSTRING];
716 static int toplevel_hidden_dir_xattr_data_len;
719 * This code creates a temporary cache with entries for each xattr which has
720 * a link count > 1 (which indicates it has one or more hard linked counterpart(s))
722 static xattr_link_cache_entry_t *xattr_link_cache_head = NULL,
723 *xattr_link_cache_tail = NULL;
725 static struct xattr_link_cache_entry *find_xattr_link_cache_entry(ino_t inum)
727 xattr_link_cache_entry_t *ptr;
729 for (ptr = xattr_link_cache_head; ptr != NULL; ptr = ptr->next)
730 if (ptr->inum == inum)
736 static void add_xattr_link_cache_entry(ino_t inum, char *target)
738 xattr_link_cache_entry_t *ptr;
740 if ((ptr = (xattr_link_cache_entry_t *)malloc(sizeof(struct xattr_link_cache_entry))) != NULL) {
741 memset((caddr_t)ptr, 0, sizeof(struct xattr_link_cache_entry));
743 strncpy(ptr->target, target, sizeof(ptr->target));
744 if (xattr_link_cache_head == NULL)
745 xattr_link_cache_head = ptr;
746 if (xattr_link_cache_tail != NULL)
747 xattr_link_cache_tail->next = ptr;
748 xattr_link_cache_tail = ptr;
752 static void drop_xattr_link_cache(void)
754 xattr_link_cache_entry_t *ptr, *next;
756 for (ptr = xattr_link_cache_tail; ptr != NULL; ptr = next) {
761 xattr_link_cache_head = NULL;
762 xattr_link_cache_tail = NULL;
765 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
767 * This function returns true if a non default extended system attribute
768 * list is associated with fd and returns false when an error has occured
769 * or when only extended system attributes other than archive,
770 * av_modified or crtime are set.
772 * The function returns true for the following cases:
774 * - any extended system attribute other than the default attributes
775 * ('archive', 'av_modified' and 'crtime') is set
776 * - nvlist has NULL name string
777 * - nvpair has data type of 'nvlist'
778 * - default data type.
780 static bool solaris_has_non_transient_extensible_attributes(int fd)
790 if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
795 while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
796 name = nvpair_name(pair);
799 fattr = name_to_attr(name);
805 type = nvpair_type(pair);
807 case DATA_TYPE_BOOLEAN_VALUE:
808 if (nvpair_value_boolean_value(pair, &value) != 0) {
811 if (value && fattr != F_ARCHIVE &&
812 fattr != F_AV_MODIFIED) {
817 case DATA_TYPE_UINT64_ARRAY:
818 if (fattr != F_CRTIME) {
823 case DATA_TYPE_NVLIST:
831 if (response != NULL)
832 nvlist_free(response);
836 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
838 #if defined(HAVE_ACL) && !defined(HAVE_EXTENDED_ACL)
840 * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
841 * There is no need to store those acls as we already store the stat bits too.
843 static bool acl_is_trivial(int count, aclent_t *entries)
848 for (n = 0; n < count; n++) {
851 if (!(ace->a_type == USER_OBJ ||
852 ace->a_type == GROUP_OBJ ||
853 ace->a_type == OTHER_OBJ ||
854 ace->a_type == CLASS_OBJ))
860 #endif /* HAVE_ACL && !HAVE_EXTENDED_ACL */
862 static bool solaris_archive_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text)
865 #ifdef HAVE_EXTENDED_ACL
870 * See if this attribute has an ACL
872 if ((fd != -1 && fpathconf(fd, _PC_ACL_ENABLED) > 0) ||
873 pathconf(attrname, _PC_ACL_ENABLED) > 0) {
875 * See if there is a non trivial acl on the file.
877 if ((fd != -1 && facl_get(fd, ACL_NO_TRIVIAL, &aclp) != 0) ||
878 acl_get(attrname, ACL_NO_TRIVIAL, &aclp) != 0) {
880 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
881 attrname, jcr->last_fname, be.bstrerror());
882 Dmsg3(100, "facl_get/acl_get of xattr %s on \"%s\" failed: ERR=%s\n",
883 attrname, jcr->last_fname, be.bstrerror());
889 #if defined(ACL_SID_FMT)
891 * New format flag added in newer Solaris versions.
893 flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
895 flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
896 #endif /* ACL_SID_FMT */
898 *acl_text = acl_totext(aclp, flags);
908 #else /* HAVE_EXTENDED_ACL */
910 aclent_t *acls = NULL;
913 * See if this attribute has an ACL
916 n = facl(fd, GETACLCNT, 0, NULL);
918 n = acl(attrname, GETACLCNT, 0, NULL);
920 if (n >= MIN_ACL_ENTRIES) {
921 acls = (aclent_t *)malloc(n * sizeof(aclent_t));
922 if ((fd != -1 && facl(fd, GETACL, n, acls) != n) ||
923 acl(attrname, GETACL, n, acls) != n) {
925 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
926 attrname, jcr->last_fname, be.bstrerror());
927 Dmsg3(100, "facl/acl of xattr %s on \"%s\" failed: ERR=%s\n",
928 attrname, jcr->last_fname, be.bstrerror());
935 * See if there is a non trivial acl on the file.
937 if (!acl_is_trivial(n, acls)) {
938 if ((*acl_text = acltotext(acls, n)) == NULL) {
940 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl text on xattr %s on file \"%s\": ERR=%s\n"),
941 attrname, jcr->last_fname, be.bstrerror());
942 Dmsg3(100, "acltotext of xattr %s on \"%s\" failed: ERR=%s\n",
943 attrname, jcr->last_fname, be.bstrerror());
958 #endif /* HAVE_EXTENDED_ACL */
961 #endif /* HAVE_ACL */
965 * Forward declaration for recursive function call.
967 static bool solaris_archive_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent);
970 * Archive an extended or extensible attribute.
971 * This is stored as an opaque stream of bytes with the following encoding:
973 * <xattr_name>\0<stat_buffer>\0<acl_string>\0<actual_xattr_data>
975 * or for a hardlinked or symlinked attribute
977 * <xattr_name>\0<stat_buffer>\0<xattr_link_source>\0
979 * xattr_name can be a subpath relative to the file the xattr is on.
980 * stat_buffer is the string representation of the stat struct.
981 * acl_string is an acl text when a non trivial acl is set on the xattr.
982 * actual_xattr_data is the content of the xattr file.
984 static bool solaris_archive_xattr(JCR *jcr, int fd, const char *xattr_namespace,
985 const char *attrname, bool toplevel_hidden_dir, int stream)
990 struct xattr_link_cache_entry *xlce;
991 char target_attrname[PATH_MAX];
992 char link_source[PATH_MAX];
993 char *acl_text = NULL;
994 char attribs[MAXSTRING];
998 snprintf(target_attrname, sizeof(target_attrname), "%s%s", xattr_namespace, attrname);
1001 * Get the stats of the extended or extensible attribute.
1003 if (fstatat(fd, attrname, &st, AT_SYMLINK_NOFOLLOW) < 0) {
1005 Jmsg3(jcr, M_ERROR, 0, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"),
1006 target_attrname, jcr->last_fname, be.bstrerror());
1007 Dmsg3(100, "fstatat of xattr %s on \"%s\" failed: ERR=%s\n",
1008 target_attrname, jcr->last_fname, be.bstrerror());
1014 * Based on the filetype perform the correct action. We support most filetypes here, more
1015 * then the actual implementation on Solaris supports so some code may never get executed
1016 * due to limitations in the implementation.
1018 switch (st.st_mode & S_IFMT) {
1023 * Get any acl on the xattr.
1025 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1029 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1030 * Encode the stat struct into an ASCII representation.
1032 encode_stat(attribs, &st, 0, stream);
1033 cnt = snprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c",
1034 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1038 * Get any acl on the xattr.
1040 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1044 * See if this is the toplevel_hidden_dir being archived.
1046 if (toplevel_hidden_dir) {
1048 * Save the data for later storage when we encounter a real xattr.
1049 * Encode the stat struct into an ASCII representation and jump out of the function.
1051 encode_stat(attribs, &st, 0, stream);
1052 toplevel_hidden_dir_xattr_data_len = snprintf(toplevel_hidden_dir_xattr_data,
1053 sizeof(toplevel_hidden_dir_xattr_data),
1055 target_attrname, 0, attribs, 0,
1056 (acl_text) ? acl_text : "", 0);
1061 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1062 * Encode the stat struct into an ASCII representation.
1064 encode_stat(attribs, &st, 0, stream);
1065 cnt = snprintf(buffer, sizeof(buffer),
1067 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1072 * If this is a hardlinked file check the inode cache for a hit.
1074 if (st.st_nlink > 1) {
1076 * See if the cache already knows this inode number.
1078 if ((xlce = find_xattr_link_cache_entry(st.st_ino)) != NULL) {
1080 * Generate a xattr encoding with the reference to the target in there.
1082 encode_stat(attribs, &st, st.st_ino, stream);
1083 cnt = snprintf(buffer, sizeof(buffer),
1085 target_attrname, 0, attribs, 0, xlce->target, 0);
1086 pm_memcpy(jcr->xattr_data, buffer, cnt);
1087 jcr->xattr_data_len = cnt;
1088 retval = send_xattr_stream(jcr, stream);
1091 * For a hard linked file we are ready now, no need to recursively archive the attributes.
1097 * Store this hard linked file in the cache.
1098 * Store the name relative to the top level xattr space.
1100 add_xattr_link_cache_entry(st.st_ino, target_attrname + 1);
1104 * Get any acl on the xattr.
1106 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1110 * Encode the stat struct into an ASCII representation.
1112 encode_stat(attribs, &st, 0, stream);
1113 cnt = snprintf(buffer, sizeof(buffer),
1115 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1118 * Open the extended or extensible attribute file.
1120 if ((attrfd = openat(fd, attrname, O_RDONLY)) < 0) {
1122 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on \"%s\": ERR=%s\n"),
1123 target_attrname, jcr->last_fname, be.bstrerror());
1124 Dmsg3(100, "openat of xattr %s on \"%s\" failed: ERR=%s\n",
1125 target_attrname, jcr->last_fname, be.bstrerror());
1132 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1133 * Encode the stat struct into an ASCII representation.
1135 if (readlink(attrname, link_source, sizeof(link_source)) < 0) {
1137 Jmsg3(jcr, M_ERROR, 0, _("Unable to read symlin %s on \"%s\": ERR=%s\n"),
1138 target_attrname, jcr->last_fname, be.bstrerror());
1139 Dmsg3(100, "readlink of xattr %s on \"%s\" failed: ERR=%s\n",
1140 target_attrname, jcr->last_fname, be.bstrerror());
1146 * Generate a xattr encoding with the reference to the target in there.
1148 encode_stat(attribs, &st, st.st_ino, stream);
1149 cnt = snprintf(buffer, sizeof(buffer),
1151 target_attrname, 0, attribs, 0, link_source, 0);
1152 pm_memcpy(jcr->xattr_data, buffer, cnt);
1153 jcr->xattr_data_len = cnt;
1154 retval = send_xattr_stream(jcr, stream);
1157 * For a soft linked file we are ready now, no need to recursively archive the attributes.
1165 * See if this is the first real xattr being saved. If it is save the toplevel_hidden_dir attributes first.
1167 if (nr_xattr_saved == 0) {
1168 pm_memcpy(jcr->xattr_data, toplevel_hidden_dir_xattr_data, toplevel_hidden_dir_xattr_data_len);
1169 jcr->xattr_data_len = toplevel_hidden_dir_xattr_data_len;
1170 send_xattr_stream(jcr, STREAM_XATTR_SOLARIS);
1173 pm_memcpy(jcr->xattr_data, buffer, cnt);
1174 jcr->xattr_data_len = cnt;
1177 * Only dump the content of regular files.
1179 switch (st.st_mode & S_IFMT) {
1181 if (st.st_size > 0) {
1183 * Protect ourself against things getting out of hand.
1185 if (st.st_size >= MAX_XATTR_STREAM) {
1186 Jmsg2(jcr, M_ERROR, 0, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
1187 jcr->last_fname, MAX_XATTR_STREAM);
1192 while ((cnt = read(attrfd, buffer, sizeof(buffer))) > 0) {
1193 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, jcr->xattr_data_len + cnt);
1194 memcpy(jcr->xattr_data + jcr->xattr_data_len, buffer, cnt);
1195 jcr->xattr_data_len += cnt;
1199 Jmsg2(jcr, M_ERROR, 0, _("Unable to read content of xattr %s on file \"%s\"\n"),
1200 target_attrname, jcr->last_fname);
1201 Dmsg2(100, "read of data from xattr %s on \"%s\" failed\n",
1202 target_attrname, jcr->last_fname);
1212 retval = send_xattr_stream(jcr, stream);
1216 * Recursivly call solaris_archive_extended_attributes for archiving the attributes
1217 * available on this extended attribute.
1220 retval = solaris_archive_xattrs(jcr, xattr_namespace, attrname);
1223 * The recursive call could change our working dir so change back to the wanted workdir.
1225 if (fchdir(fd) < 0) {
1227 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"),
1228 jcr->last_fname, be.bstrerror());
1229 Dmsg3(100, "Unable to fchdir to xattr space of file \"%s\" using fd %d: ERR=%s\n",
1230 jcr->last_fname, fd, be.bstrerror());
1245 static bool solaris_archive_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent)
1248 int fd, filefd = -1, attrdirfd = -1;
1251 char current_xattr_namespace[PATH_MAX];
1252 bool retval = false;
1255 * Determine what argument to use. Use attr_parent when set
1256 * (recursive call) or jcr->last_fname for first call. Also save
1257 * the current depth of the xattr_space we are in.
1261 if (xattr_namespace)
1262 snprintf(current_xattr_namespace, sizeof(current_xattr_namespace), "%s%s/",
1263 xattr_namespace, attr_parent);
1265 strcpy(current_xattr_namespace, "/");
1267 name = jcr->last_fname;
1268 strcpy(current_xattr_namespace, "/");
1272 * Open the file on which to archive the xattrs read-only.
1274 if ((filefd = open(name, O_RDONLY | O_NONBLOCK)) < 0) {
1276 Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"),
1277 jcr->last_fname, be.bstrerror());
1278 Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1279 jcr->last_fname, be.bstrerror());
1285 * Open the xattr naming space.
1287 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1291 * Gentile way of the system saying this type of xattr layering is not supported.
1292 * Which is not problem we just forget about this this xattr.
1293 * But as this is not an error we return a positive return value.
1299 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1300 name, jcr->last_fname, be.bstrerror());
1301 Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1302 name, jcr->last_fname, be.bstrerror());
1309 * We need to change into the attribute directory to determine if each of the
1310 * attributes should be archived.
1312 if (fchdir(attrdirfd) < 0) {
1314 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1315 jcr->last_fname, be.bstrerror());
1316 Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1317 jcr->last_fname, attrdirfd, be.bstrerror());
1323 * Save the data of the toplevel xattr hidden_dir. We save this one before anything
1324 * else because the readdir returns "." entry after the extensible attr entry.
1325 * And as we want this entry before anything else we better just save its data.
1328 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, ".",
1329 true, STREAM_XATTR_SOLARIS);
1331 if ((fd = dup(attrdirfd)) == -1 ||
1332 (dirp = fdopendir(fd)) == (DIR *)NULL) {
1334 Jmsg2(jcr, M_ERROR, 0, _("Unable to list the xattr space on file \"%s\": ERR=%s\n"),
1335 jcr->last_fname, be.bstrerror());
1336 Dmsg3(100, "Unable to fdopendir xattr space on file \"%s\" using fd %d: ERR=%s\n",
1337 jcr->last_fname, fd, be.bstrerror());
1343 * Walk the namespace.
1345 while (dp = readdir(dirp)) {
1347 * Skip only the toplevel . dir.
1349 if (!attr_parent && !strcmp(dp->d_name, "."))
1353 * Skip all .. directories
1355 if (!strcmp(dp->d_name, ".."))
1358 Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
1359 current_xattr_namespace, dp->d_name, jcr->last_fname);
1361 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1363 * We are not interested in read-only extensible attributes.
1365 if (!strcmp(dp->d_name, VIEW_READONLY)) {
1366 Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
1367 current_xattr_namespace, dp->d_name, jcr->last_fname);
1373 * We are only interested in read-write extensible attributes
1374 * when they contain non-transient values.
1376 if (!strcmp(dp->d_name, VIEW_READWRITE)) {
1378 * Determine if there are non-transient system attributes at the toplevel.
1379 * We need to provide a fd to the open file.
1381 if (!solaris_has_non_transient_extensible_attributes(filefd)) {
1382 Dmsg3(400, "Skipping transient extensible attributes %s%s on file \"%s\"\n",
1383 current_xattr_namespace, dp->d_name, jcr->last_fname);
1389 * Archive the xattr.
1391 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1392 false, STREAM_XATTR_SOLARIS_SYS);
1395 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
1398 * Archive the xattr.
1400 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1401 false, STREAM_XATTR_SOLARIS);
1408 if (attrdirfd != -1)
1417 static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, char *acl_text)
1419 #ifdef HAVE_EXTENDED_ACL
1423 if ((error = acl_fromtext(acl_text, &aclp)) != 0) {
1427 if ((fd != -1 && facl_set(fd, aclp) != 0) ||
1428 acl_set(attrname, aclp) != 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());
1442 #else /* HAVE_EXTENDED_ACL */
1444 aclent_t *acls = NULL;
1446 acls = aclfromtext(acl_text, &n);
1448 if ((fd != -1 && facl(fd, SETACL, n, acls) != 0) ||
1449 acl(attrname, SETACL, n, acls) != 0) {
1451 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1452 attrname, jcr->last_fname, be.bstrerror());
1453 Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1454 attrname, jcr->last_fname, be.bstrerror());
1464 #endif /* HAVE_EXTENDED_ACL */
1466 #endif /* HAVE_ACL */
1468 static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible)
1470 int fd, filefd = -1, attrdirfd = -1, attrfd = -1;
1471 int used_bytes, total_bytes, cnt;
1472 char *bp, *target_attrname, *attribs;
1473 char *linked_target = NULL;
1474 char *acl_text = NULL;
1478 struct timeval times[2];
1479 bool retval = false;
1482 * Parse the xattr stream. First the part that is the same for all xattrs.
1485 total_bytes = jcr->xattr_data_len;
1488 * The name of the target xattr has a leading / we are not interested
1489 * in that so skip it when decoding the string. We always start a the /
1490 * of the xattr space anyway.
1492 target_attrname = jcr->xattr_data + 1;
1493 if ((bp = strchr(target_attrname, '\0')) == (char *)NULL ||
1494 (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
1500 * Open the file on which to restore the xattrs read-only.
1502 if ((filefd = open(jcr->last_fname, O_RDONLY | O_NONBLOCK)) < 0) {
1504 Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"),
1505 jcr->last_fname, be.bstrerror());
1506 Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1507 jcr->last_fname, be.bstrerror());
1513 * Open the xattr naming space and make it the current working dir.
1515 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1517 Jmsg2(jcr, M_ERROR, 0, _("Unable to open xattr space on file \"%s\": ERR=%s\n"),
1518 jcr->last_fname, be.bstrerror());
1519 Dmsg2(100, "Unable to open xattr space on file \"%s\": ERR=%s\n",
1520 jcr->last_fname, be.bstrerror());
1525 if (fchdir(attrdirfd) < 0) {
1527 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1528 jcr->last_fname, be.bstrerror());
1529 Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1530 jcr->last_fname, attrdirfd, be.bstrerror());
1536 * Try to open the correct xattr subdir based on the target_attrname given.
1537 * e.g. check if its a subdir attrname. Each / in the string makes us go
1540 while ((bp = strchr(target_attrname, '/')) != (char *)NULL) {
1543 if ((fd = open(target_attrname, O_RDONLY | O_NONBLOCK)) < 0) {
1545 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1546 target_attrname, jcr->last_fname, be.bstrerror());
1547 Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1548 target_attrname, jcr->last_fname, be.bstrerror());
1557 * Open the xattr naming space.
1559 if ((fd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1561 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1562 target_attrname, jcr->last_fname, be.bstrerror());
1563 Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1564 target_attrname, jcr->last_fname, be.bstrerror());
1573 * Make the xattr space our current workingdir.
1575 if (fchdir(attrdirfd) < 0) {
1577 Jmsg3(jcr, M_ERROR, 0, _("Unable to chdir to xattr space %s on file \"%s\": ERR=%s\n"),
1578 target_attrname, jcr->last_fname, be.bstrerror());
1579 Dmsg4(100, "Unable to fchdir to xattr space %s on file \"%s\" using fd %d: ERR=%s\n",
1580 target_attrname, jcr->last_fname, attrdirfd, be.bstrerror());
1585 target_attrname = ++bp;
1589 * Decode the attributes from the stream.
1591 decode_stat(attribs, &st, &inum);
1594 * Decode the next field (acl_text).
1596 if ((bp = strchr(attribs, '\0')) == (char *)NULL ||
1597 (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
1603 * Based on the filetype perform the correct action. We support most filetypes here, more
1604 * then the actual implementation on Solaris supports so some code may never get executed
1605 * due to limitations in the implementation.
1607 switch (st.st_mode & S_IFMT) {
1610 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1612 unlinkat(attrdirfd, target_attrname, 0);
1613 if (mkfifo(target_attrname, st.st_mode) < 0) {
1615 Jmsg3(jcr, M_ERROR, 0, _("Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n"),
1616 target_attrname, jcr->last_fname, be.bstrerror());
1617 Dmsg3(100, "Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n",
1618 target_attrname, jcr->last_fname, be.bstrerror());
1626 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1628 unlinkat(attrdirfd, target_attrname, 0);
1629 if (mknod(target_attrname, st.st_mode, st.st_rdev) < 0) {
1631 Jmsg3(jcr, M_ERROR, 0, _("Unable to mknod xattr %s on file \"%s\": ERR=%s\n"),
1632 target_attrname, jcr->last_fname, be.bstrerror());
1633 Dmsg3(100, "Unable to mknod xattr %s on file \"%s\": ERR=%s\n",
1634 target_attrname, jcr->last_fname, be.bstrerror());
1641 * If its not the hidden_dir create the entry.
1642 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1644 if (strcmp(target_attrname, ".")) {
1645 unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
1646 if (mkdir(target_attrname, st.st_mode) < 0) {
1648 Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
1649 target_attrname, jcr->last_fname, be.bstrerror());
1650 Dmsg3(100, "Unable to mkdir xattr %s on file \"%s\": ERR=%s\n",
1651 target_attrname, jcr->last_fname, be.bstrerror());
1659 * See if this is a hard linked file. e.g. inum != 0
1664 unlinkat(attrdirfd, target_attrname, 0);
1665 if (link(linked_target, target_attrname) < 0) {
1667 Jmsg4(jcr, M_ERROR, 0, _("Unable to link xattr %s to %s on file \"%s\": ERR=%s\n"),
1668 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1669 Dmsg4(100, "Unable to link xattr %s to %s on file \"%s\": ERR=%s\n",
1670 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1676 * Successfully restored xattr.
1681 if ((bp = strchr(acl_text, '\0')) == (char *)NULL ||
1682 (used_bytes = (bp - jcr->xattr_data)) >= total_bytes) {
1686 if (used_bytes < (total_bytes - 1))
1690 * Restore the actual xattr.
1692 if (!is_extensible) {
1693 unlinkat(attrdirfd, target_attrname, 0);
1696 if ((attrfd = openat(attrdirfd, target_attrname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) {
1698 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1699 target_attrname, jcr->last_fname, be.bstrerror());
1700 Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1701 target_attrname, jcr->last_fname, be.bstrerror());
1708 * Restore the actual data.
1710 if (st.st_size > 0) {
1711 used_bytes = (data - jcr->xattr_data);
1712 cnt = total_bytes - used_bytes;
1715 * Do a sanity check, the st.st_size should be the same as the number of bytes
1716 * we have available as data of the stream.
1718 if (cnt != st.st_size) {
1719 Jmsg2(jcr, M_ERROR, 0, _("Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n"),
1720 target_attrname, jcr->last_fname);
1721 Dmsg2(100, "Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n",
1722 target_attrname, jcr->last_fname);
1728 cnt = write(attrfd, data, cnt);
1731 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore data of xattr %s on file \"%s\": ERR=%s\n"),
1732 target_attrname, jcr->last_fname, be.bstrerror());
1733 Dmsg3(100, "Unable to restore data of xattr %s on file \"%s\": ERR=%s\n",
1734 target_attrname, jcr->last_fname, be.bstrerror());
1741 cnt = total_bytes - used_bytes;
1747 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1751 if (symlink(linked_target, target_attrname) < 0) {
1753 Jmsg4(jcr, M_ERROR, 0, _("Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n"),
1754 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1755 Dmsg4(100, "Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n",
1756 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1762 * Successfully restored xattr.
1771 * Restore owner and acl for non extensible attributes.
1773 if (!is_extensible) {
1774 if (fchownat(attrdirfd, target_attrname, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW) < 0) {
1778 * Gentile way of the system saying this type of xattr layering is not supported.
1779 * But as this is not an error we return a positive return value.
1785 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n"),
1786 target_attrname, jcr->last_fname, be.bstrerror());
1787 Dmsg3(100, "Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n",
1788 target_attrname, jcr->last_fname, be.bstrerror());
1796 if (acl_text && *acl_text)
1797 if (!solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text))
1799 #endif /* HAVE_ACL */
1802 * For a non extensible attribute restore access and modification time on the xattr.
1804 if (!is_extensible) {
1805 times[0].tv_sec = st.st_atime;
1806 times[0].tv_usec = 0;
1807 times[1].tv_sec = st.st_mtime;
1808 times[1].tv_usec = 0;
1810 if (futimesat(attrdirfd, target_attrname, times) < 0) {
1812 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n"),
1813 target_attrname, jcr->last_fname, be.bstrerror());
1814 Dmsg3(100, "Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n",
1815 target_attrname, jcr->last_fname, be.bstrerror());
1822 * Successfully restored xattr.
1828 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n"),
1830 Dmsg1(100, "Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n",
1836 if (attrdirfd != -1)
1844 static bool solaris_extract_xattr(JCR *jcr, int stream)
1847 bool is_extensible = false;
1851 * First make sure we can restore xattr on the filesystem.
1854 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1855 case STREAM_XATTR_SOLARIS_SYS:
1856 if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
1857 Qmsg1(jcr, M_WARNING, 0,
1858 _("Failed to restore extensible attributes on file \"%s\"\n"),
1860 Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n",
1866 is_extensible = true;
1869 case STREAM_XATTR_SOLARIS:
1870 if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
1871 Qmsg1(jcr, M_WARNING, 0,
1872 _("Failed to restore extended attributes on file \"%s\"\n"),
1874 Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n",
1886 * As we change the cwd in the restore function save the current cwd
1887 * for restore after return from the solaris_restore_xattrs function.
1889 getcwd(cwd, sizeof(cwd));
1890 retval = solaris_restore_xattrs(jcr, is_extensible);
1896 static int solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1902 * First see if extended attributes or extensible attributes are present.
1903 * If not just pretend things went ok.
1905 if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) {
1909 * As we change the cwd in the archive function save the current cwd
1910 * for restore after return from the solaris_archive_xattrs function.
1912 getcwd(cwd, sizeof(cwd));
1913 retval = solaris_archive_xattrs(jcr, NULL, NULL);
1916 drop_xattr_link_cache();
1922 static bool solaris_parse_xattr_stream(JCR *jcr, int stream)
1925 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1926 case STREAM_XATTR_SOLARIS_SYS:
1928 case STREAM_XATTR_SOLARIS:
1929 return solaris_extract_xattr(jcr, stream);
1936 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1938 #if defined(HAVE_SUN_OS)
1939 return solaris_build_xattr_streams(jcr, ff_pkt);
1940 #elif defined(HAVE_DARWIN_OS)
1941 return darwin_build_xattr_streams(jcr, ff_pkt);
1942 #elif defined(HAVE_FREEBSD_OS)
1943 return freebsd_build_xattr_streams(jcr, ff_pkt);
1944 #elif defined(HAVE_LINUX_OS)
1945 return linux_build_xattr_streams(jcr, ff_pkt);
1946 #elif defined(HAVE_NETBSD_OS)
1947 return netbsd_build_xattr_streams(jcr, ff_pkt);
1951 bool parse_xattr_stream(JCR *jcr, int stream)
1954 * Based on the stream being passed in dispatch to the right function
1955 * for parsing and restoring a specific xattr. The platform determines
1956 * which streams are recognized and parsed and which are handled by
1957 * the default case and ignored. As only one of the platform defines
1958 * is true per compile we never end up with duplicate switch values.
1961 #if defined(HAVE_SUN_OS)
1962 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1963 case STREAM_XATTR_SOLARIS_SYS:
1965 case STREAM_XATTR_SOLARIS:
1966 return solaris_parse_xattr_stream(jcr, stream);
1967 #elif defined(HAVE_DARWIN_OS)
1968 case STREAM_XATTR_DARWIN:
1969 return darwin_parse_xattr_stream(jcr, stream);
1970 #elif defined(HAVE_FREEBSD_OS)
1971 case STREAM_XATTR_FREEBSD:
1972 return freebsd_parse_xattr_stream(jcr, stream);
1973 #elif defined(HAVE_LINUX_OS)
1974 case STREAM_XATTR_LINUX:
1975 return linux_parse_xattr_stream(jcr, stream);
1976 #elif defined(HAVE_NETBSD_OS)
1977 case STREAM_XATTR_NETBSD:
1978 return netbsd_parse_xattr_stream(jcr, stream);
1982 * Issue a warning and discard the message. But pretend the restore was ok.
1984 Qmsg2(jcr, M_WARNING, 0,
1985 _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
1986 jcr->last_fname, stream);
1988 } /* end switch (stream) */