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;
325 * Allocate enough room to hold all extended attributes.
326 * After allocating the storage make sure its empty by zeroing it.
328 if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
329 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
333 memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
336 * Walk the list of extended attributes names and retrieve the data.
337 * We already count the bytes needed for serializing the stream later on.
339 current_xattr = xattr_value_list;
341 while ((bp - xattr_list) + 1 < xattr_list_len) {
342 #if defined(HAVE_LINUX_OS)
343 if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
344 bp = strchr(bp, '\0') + 1;
351 * Each xattr valuepair starts with a magic so we can parse it easier.
353 current_xattr->magic = XATTR_MAGIC;
354 expected_serialize_len += sizeof(current_xattr->magic);
357 * Allocate space for storing the name.
359 current_xattr->name_length = strlen(bp);
360 if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
361 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
365 memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
367 expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
370 * First see how long the value is for the extended attribute.
372 xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
373 if (xattr_value_len < 0) {
375 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
376 jcr->last_fname, be.bstrerror());
377 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
378 jcr->last_fname, be.bstrerror());
384 * Allocate space for storing the value.
386 if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
387 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
391 memset((caddr_t)current_xattr->value, 0, xattr_value_len);
393 xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
394 if (xattr_value_len < 0) {
396 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
397 jcr->last_fname, be.bstrerror());
398 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
399 jcr->last_fname, be.bstrerror());
405 * Store the actual length of the value.
407 current_xattr->value_length = xattr_value_len;
408 expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
411 * Protect ourself against things getting out of hand.
413 if (expected_serialize_len >= MAX_XATTR_STREAM) {
414 Jmsg2(jcr, M_ERROR, 0, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
415 jcr->last_fname, MAX_XATTR_STREAM);
424 bp = strchr(bp, '\0') + 1;
428 * Serialize the datastream.
430 if (serialize_xattr_stream(jcr, expected_serialize_len, xattr_value_list) < expected_serialize_len) {
431 Jmsg1(jcr, M_ERROR, 0, _("Failed to serialize extended attributes on file \"%s\"\n"),
433 Dmsg1(100, "Failed to serialize extended attributes on file \"%s\"\n",
439 xattr_drop_internal_table(xattr_value_list);
443 * Send the datastream to the SD.
445 return send_xattr_stream(jcr, stream);
448 xattr_drop_internal_table(xattr_value_list);
454 static bool generic_xattr_parse_streams(JCR *jcr)
457 xattr_t current_xattr;
461 * Parse the stream and perform the setxattr calls on the file.
463 * Start unserializing the data. We keep on looping while we have not
464 * unserialized all bytes in the stream.
466 unser_begin(jcr->xattr_data, jcr->xattr_data_len);
467 while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
469 * First make sure the magic is present. This way we can easily catch corruption.
470 * Any missing MAGIC is fatal we do NOT try to continue.
472 unser_uint32(current_xattr.magic);
473 if (current_xattr.magic != XATTR_MAGIC) {
474 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
476 Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
483 * Decode the valuepair. First decode the length of the name.
485 unser_uint32(current_xattr.name_length);
488 * Allocate room for the name and decode its content.
490 if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
491 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
495 unser_bytes(current_xattr.name, current_xattr.name_length);
498 * The xattr_name needs to be null terminated for lsetxattr.
500 current_xattr.name[current_xattr.name_length] = '\0';
503 * Decode the value length.
505 unser_uint32(current_xattr.value_length);
508 * Allocate room for the value and decode its content.
510 if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
511 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
515 unser_bytes(current_xattr.value, current_xattr.value_length);
518 * Try to set the extended attribute on the file.
519 * If we fail to set this attribute we flag the error but its not fatal,
520 * we try to restore the other extended attributes too.
522 if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
523 current_xattr.value_length, 0) != 0) {
525 Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
526 jcr->last_fname, be.bstrerror());
527 Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
528 jcr->last_fname, be.bstrerror());
531 * Reset the return flag to false to indicate one or more extended attributes
532 * could not be restored.
538 * Free the temporary buffers.
540 free(current_xattr.name);
541 free(current_xattr.value);
544 unser_end(jcr->xattr_data, jcr->xattr_data_len);
548 #if defined(HAVE_DARWIN_OS)
549 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
551 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
554 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
557 case STREAM_XATTR_DARWIN:
558 return generic_xattr_parse_streams(jcr);
563 #elif defined(HAVE_FREEBSD_OS)
564 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
566 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
569 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
572 case STREAM_XATTR_FREEBSD:
573 return generic_xattr_parse_streams(jcr);
578 #elif defined(HAVE_LINUX_OS)
579 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
581 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
584 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
587 case STREAM_XATTR_LINUX:
588 return generic_xattr_parse_streams(jcr);
593 #elif defined(HAVE_NETBSD_OS)
594 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
596 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
599 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
602 case STREAM_XATTR_NETBSD:
603 return generic_xattr_parse_streams(jcr);
609 #elif defined(HAVE_SUN_OS)
611 * Solaris extended attributes were introduced in Solaris 9
614 * Solaris extensible attributes were introduced in OpenSolaris
615 * by PSARC 2007/315 Solaris extensible attributes are also
616 * sometimes called extended system attributes.
618 * man fsattr(5) on Solaris gives a wealth of info. The most
619 * important bits are:
621 * Attributes are logically supported as files within the file
622 * system. The file system is therefore augmented with an
623 * orthogonal name space of file attributes. Any file (includ-
624 * ing attribute files) can have an arbitrarily deep attribute
625 * tree associated with it. Attribute values are accessed by
626 * file descriptors obtained through a special attribute inter-
627 * face. This logical view of "attributes as files" allows the
628 * leveraging of existing file system interface functionality
629 * to support the construction, deletion, and manipulation of
632 * The special files "." and ".." retain their accustomed
633 * semantics within the attribute hierarchy. The "." attribute
634 * file refers to the current directory and the ".." attribute
635 * file refers to the parent directory. The unnamed directory
636 * at the head of each attribute tree is considered the "child"
637 * of the file it is associated with and the ".." file refers
638 * to the associated file. For any non-directory file with
639 * attributes, the ".." entry in the unnamed directory refers
640 * to a file that is not a directory.
642 * Conceptually, the attribute model is fully general. Extended
643 * attributes can be any type of file (doors, links, direc-
644 * tories, and so forth) and can even have their own attributes
645 * (fully recursive). As a result, the attributes associated
646 * with a file could be an arbitrarily deep directory hierarchy
647 * where each attribute could have an equally complex attribute
648 * tree associated with it. Not all implementations are able
649 * to, or want to, support the full model. Implementation are
650 * therefore permitted to reject operations that are not sup-
651 * ported. For example, the implementation for the UFS file
652 * system allows only regular files as attributes (for example,
653 * no sub-directories) and rejects attempts to place attributes
656 * The following list details the operations that are rejected
657 * in the current implementation:
659 * link Any attempt to create links between
660 * attribute and non-attribute space
661 * is rejected to prevent security-
662 * related or otherwise sensitive
663 * attributes from being exposed, and
664 * therefore manipulable, as regular
667 * rename Any attempt to rename between
668 * attribute and non-attribute space
669 * is rejected to prevent an already
670 * linked file from being renamed and
671 * thereby circumventing the link res-
674 * mkdir, symlink, mknod Any attempt to create a "non-
675 * regular" file in attribute space is
676 * rejected to reduce the functional-
677 * ity, and therefore exposure and
678 * risk, of the initial implementa-
681 * The entire available name space has been allocated to "gen-
682 * eral use" to bring the implementation in line with the NFSv4
683 * draft standard [NFSv4]. That standard defines "named attri-
684 * butes" (equivalent to Solaris Extended Attributes) with no
685 * naming restrictions. All Sun applications making use of
686 * opaque extended attributes will use the prefix "SUNW".
689 #ifdef HAVE_SYS_ATTR_H
690 #include <sys/attr.h>
697 #ifdef HAVE_SYS_NVPAIR_H
698 #include <sys/nvpair.h>
701 #ifdef HAVE_SYS_ACL_H
706 * This is the count of xattrs saved on a certain file, it gets reset
707 * on each new file processed and is used to see if we need to send
708 * the hidden xattr dir data. We only send that data when we encounter
709 * an other xattr on the file.
711 static int nr_xattr_saved = 0;
712 static char toplevel_hidden_dir_xattr_data[MAXSTRING];
713 static int toplevel_hidden_dir_xattr_data_len;
716 * This code creates a temporary cache with entries for each xattr which has
717 * a link count > 1 (which indicates it has one or more hard linked counterpart(s))
719 static xattr_link_cache_entry_t *xattr_link_cache_head = NULL,
720 *xattr_link_cache_tail = NULL;
722 static struct xattr_link_cache_entry *find_xattr_link_cache_entry(ino_t inum)
724 xattr_link_cache_entry_t *ptr;
726 for (ptr = xattr_link_cache_head; ptr != NULL; ptr = ptr->next)
727 if (ptr->inum == inum)
733 static void add_xattr_link_cache_entry(ino_t inum, char *target)
735 xattr_link_cache_entry_t *ptr;
737 if ((ptr = (xattr_link_cache_entry_t *)malloc(sizeof(struct xattr_link_cache_entry))) != NULL) {
738 memset((caddr_t)ptr, 0, sizeof(struct xattr_link_cache_entry));
740 strncpy(ptr->target, target, sizeof(ptr->target));
741 if (xattr_link_cache_head == NULL)
742 xattr_link_cache_head = ptr;
743 xattr_link_cache_tail = ptr;
747 static void drop_xattr_link_cache(void)
749 xattr_link_cache_entry_t *ptr, *next;
751 for (ptr = xattr_link_cache_tail; ptr != NULL; ptr = next) {
756 xattr_link_cache_head = NULL;
757 xattr_link_cache_tail = NULL;
760 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
762 * This function returns true if a non default extended system attribute
763 * list is associated with fd and returns false when an error has occured
764 * or when only extended system attributes other than archive,
765 * av_modified or crtime are set.
767 * The function returns true for the following cases:
769 * - any extended system attribute other than the default attributes
770 * ('archive', 'av_modified' and 'crtime') is set
771 * - nvlist has NULL name string
772 * - nvpair has data type of 'nvlist'
773 * - default data type.
775 static bool solaris_has_non_transient_extensible_attributes(int fd)
785 if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
790 while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
791 name = nvpair_name(pair);
794 fattr = name_to_attr(name);
800 type = nvpair_type(pair);
802 case DATA_TYPE_BOOLEAN_VALUE:
803 if (nvpair_value_boolean_value(pair, &value) != 0) {
806 if (value && fattr != F_ARCHIVE &&
807 fattr != F_AV_MODIFIED) {
812 case DATA_TYPE_UINT64_ARRAY:
813 if (fattr != F_CRTIME) {
818 case DATA_TYPE_NVLIST:
826 if (response != NULL)
827 nvlist_free(response);
831 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
833 #if defined(HAVE_ACL) && !defined(HAVE_EXTENDED_ACL)
835 * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
836 * There is no need to store those acls as we already store the stat bits too.
838 static bool acl_is_trivial(int count, aclent_t *entries)
843 for (n = 0; n < count; n++) {
846 if (!(ace->a_type == USER_OBJ ||
847 ace->a_type == GROUP_OBJ ||
848 ace->a_type == OTHER_OBJ ||
849 ace->a_type == CLASS_OBJ))
855 #endif /* HAVE_ACL && !HAVE_EXTENDED_ACL */
857 static bool solaris_archive_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text)
860 #ifdef HAVE_EXTENDED_ACL
865 * See if this attribute has an ACL
867 if ((fd != -1 && fpathconf(fd, _PC_ACL_ENABLED) > 0) ||
868 pathconf(attrname, _PC_ACL_ENABLED) > 0) {
870 * See if there is a non trivial acl on the file.
872 if ((fd != -1 && facl_get(fd, ACL_NO_TRIVIAL, &aclp) != 0) ||
873 acl_get(attrname, ACL_NO_TRIVIAL, &aclp) != 0) {
875 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
876 attrname, jcr->last_fname, be.bstrerror());
877 Dmsg3(100, "facl_get/acl_get of xattr %s on \"%s\" failed: ERR=%s\n",
878 attrname, jcr->last_fname, be.bstrerror());
884 #if defined(ACL_SID_FMT)
886 * New format flag added in newer Solaris versions.
888 flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
890 flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
891 #endif /* ACL_SID_FMT */
893 *acl_text = acl_totext(aclp, flags);
903 #else /* HAVE_EXTENDED_ACL */
905 aclent_t *acls = NULL;
908 * See if this attribute has an ACL
911 n = facl(fd, GETACLCNT, 0, NULL);
913 n = acl(attrname, GETACLCNT, 0, NULL);
915 if (n >= MIN_ACL_ENTRIES) {
916 acls = (aclent_t *)malloc(n * sizeof(aclent_t));
917 if ((fd != -1 && facl(fd, GETACL, n, acls) != n) ||
918 acl(attrname, GETACL, n, acls) != n) {
920 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
921 attrname, jcr->last_fname, be.bstrerror());
922 Dmsg3(100, "facl/acl of xattr %s on \"%s\" failed: ERR=%s\n",
923 attrname, jcr->last_fname, be.bstrerror());
930 * See if there is a non trivial acl on the file.
932 if (!acl_is_trivial(n, acls)) {
933 if ((*acl_text = acltotext(acls, n)) == NULL) {
935 Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl text on xattr %s on file \"%s\": ERR=%s\n"),
936 attrname, jcr->last_fname, be.bstrerror());
937 Dmsg3(100, "acltotext of xattr %s on \"%s\" failed: ERR=%s\n",
938 attrname, jcr->last_fname, be.bstrerror());
953 #endif /* HAVE_EXTENDED_ACL */
956 #endif /* HAVE_ACL */
960 * Forward declaration for recursive function call.
962 static bool solaris_archive_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent);
965 * Archive an extended or extensible attribute.
966 * This is stored as an opaque stream of bytes with the following encoding:
968 * <xattr_name>\0<stat_buffer>\0<acl_string>\0<actual_xattr_data>
970 * or for a hardlinked or symlinked attribute
972 * <xattr_name>\0<stat_buffer>\0<xattr_link_source>\0
974 * xattr_name can be a subpath relative to the file the xattr is on.
975 * stat_buffer is the string representation of the stat struct.
976 * acl_string is an acl text when a non trivial acl is set on the xattr.
977 * actual_xattr_data is the content of the xattr file.
979 static bool solaris_archive_xattr(JCR *jcr, int fd, const char *xattr_namespace,
980 const char *attrname, bool toplevel_hidden_dir, int stream)
985 struct xattr_link_cache_entry *xlce;
986 char target_attrname[PATH_MAX];
987 char link_source[PATH_MAX];
988 char *acl_text = NULL;
989 char attribs[MAXSTRING];
993 snprintf(target_attrname, sizeof(target_attrname), "%s%s", xattr_namespace, attrname);
996 * Get the stats of the extended or extensible attribute.
998 if (fstatat(fd, attrname, &st, AT_SYMLINK_NOFOLLOW) < 0) {
1000 Jmsg3(jcr, M_ERROR, 0, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"),
1001 target_attrname, jcr->last_fname, be.bstrerror());
1002 Dmsg3(100, "fstatat of xattr %s on \"%s\" failed: ERR=%s\n",
1003 target_attrname, jcr->last_fname, be.bstrerror());
1009 * Based on the filetype perform the correct action. We support most filetypes here, more
1010 * then the actual implementation on Solaris supports so some code may never get executed
1011 * due to limitations in the implementation.
1013 switch (st.st_mode & S_IFMT) {
1018 * Get any acl on the xattr.
1020 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1024 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1025 * Encode the stat struct into an ASCII representation.
1027 encode_stat(attribs, &st, 0, stream);
1028 cnt = snprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c",
1029 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1033 * Get any acl on the xattr.
1035 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1039 * See if this is the toplevel_hidden_dir being archived.
1041 if (toplevel_hidden_dir) {
1043 * Save the data for later storage when we encounter a real xattr.
1044 * Encode the stat struct into an ASCII representation and jump out of the function.
1046 encode_stat(attribs, &st, 0, stream);
1047 toplevel_hidden_dir_xattr_data_len = snprintf(toplevel_hidden_dir_xattr_data,
1048 sizeof(toplevel_hidden_dir_xattr_data),
1050 target_attrname, 0, attribs, 0,
1051 (acl_text) ? acl_text : "", 0);
1056 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1057 * Encode the stat struct into an ASCII representation.
1059 encode_stat(attribs, &st, 0, stream);
1060 cnt = snprintf(buffer, sizeof(buffer),
1062 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1067 * If this is a hardlinked file check the inode cache for a hit.
1069 if (st.st_nlink > 1) {
1071 * See if the cache already knows this inode number.
1073 if ((xlce = find_xattr_link_cache_entry(st.st_ino)) != NULL) {
1075 * Generate a xattr encoding with the reference to the target in there.
1077 encode_stat(attribs, &st, st.st_ino, stream);
1078 cnt = snprintf(buffer, sizeof(buffer),
1080 target_attrname, 0, attribs, 0, xlce->target, 0);
1081 pm_memcpy(jcr->xattr_data, buffer, cnt);
1082 jcr->xattr_data_len = cnt;
1083 retval = send_xattr_stream(jcr, stream);
1086 * For a hard linked file we are ready now, no need to recursively archive the attributes.
1092 * Store this hard linked file in the cache.
1093 * Store the name relative to the top level xattr space.
1095 add_xattr_link_cache_entry(st.st_ino, target_attrname + 1);
1099 * Get any acl on the xattr.
1101 if (!solaris_archive_xattr_acl(jcr, attrfd, attrname, &acl_text))
1105 * Encode the stat struct into an ASCII representation.
1107 encode_stat(attribs, &st, 0, stream);
1108 cnt = snprintf(buffer, sizeof(buffer),
1110 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1113 * Open the extended or extensible attribute file.
1115 if ((attrfd = openat(fd, attrname, O_RDONLY)) < 0) {
1117 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on \"%s\": ERR=%s\n"),
1118 target_attrname, jcr->last_fname, be.bstrerror());
1119 Dmsg3(100, "openat of xattr %s on \"%s\" failed: ERR=%s\n",
1120 target_attrname, jcr->last_fname, be.bstrerror());
1127 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1128 * Encode the stat struct into an ASCII representation.
1130 if (readlink(attrname, link_source, sizeof(link_source)) < 0) {
1132 Jmsg3(jcr, M_ERROR, 0, _("Unable to read symlin %s on \"%s\": ERR=%s\n"),
1133 target_attrname, jcr->last_fname, be.bstrerror());
1134 Dmsg3(100, "readlink of xattr %s on \"%s\" failed: ERR=%s\n",
1135 target_attrname, jcr->last_fname, be.bstrerror());
1141 * Generate a xattr encoding with the reference to the target in there.
1143 encode_stat(attribs, &st, st.st_ino, stream);
1144 cnt = snprintf(buffer, sizeof(buffer),
1146 target_attrname, 0, attribs, 0, link_source, 0);
1147 pm_memcpy(jcr->xattr_data, buffer, cnt);
1148 jcr->xattr_data_len = cnt;
1149 retval = send_xattr_stream(jcr, stream);
1152 * For a soft linked file we are ready now, no need to recursively archive the attributes.
1160 * See if this is the first real xattr being saved. If it is save the toplevel_hidden_dir attributes first.
1162 if (nr_xattr_saved == 0) {
1163 pm_memcpy(jcr->xattr_data, toplevel_hidden_dir_xattr_data, toplevel_hidden_dir_xattr_data_len);
1164 jcr->xattr_data_len = toplevel_hidden_dir_xattr_data_len;
1165 send_xattr_stream(jcr, STREAM_XATTR_SOLARIS);
1168 pm_memcpy(jcr->xattr_data, buffer, cnt);
1169 jcr->xattr_data_len = cnt;
1172 * Only dump the content of regular files.
1174 switch (st.st_mode & S_IFMT) {
1176 if (st.st_size > 0) {
1178 * Protect ourself against things getting out of hand.
1180 if (st.st_size >= MAX_XATTR_STREAM) {
1181 Jmsg2(jcr, M_ERROR, 0, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
1182 jcr->last_fname, MAX_XATTR_STREAM);
1187 while ((cnt = read(attrfd, buffer, sizeof(buffer))) > 0) {
1188 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, jcr->xattr_data_len + cnt);
1189 memcpy(jcr->xattr_data + jcr->xattr_data_len, buffer, cnt);
1190 jcr->xattr_data_len += cnt;
1194 Jmsg2(jcr, M_ERROR, 0, _("Unable to read content of xattr %s on file \"%s\"\n"),
1195 target_attrname, jcr->last_fname);
1196 Dmsg2(100, "read of data from xattr %s on \"%s\" failed\n",
1197 target_attrname, jcr->last_fname);
1207 retval = send_xattr_stream(jcr, stream);
1211 * Recursivly call solaris_archive_extended_attributes for archiving the attributes
1212 * available on this extended attribute.
1215 retval = solaris_archive_xattrs(jcr, xattr_namespace, attrname);
1218 * The recursive call could change our working dir so change back to the wanted workdir.
1220 if (fchdir(fd) < 0) {
1222 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"),
1223 jcr->last_fname, be.bstrerror());
1224 Dmsg3(100, "Unable to fchdir to xattr space of file \"%s\" using fd %d: ERR=%s\n",
1225 jcr->last_fname, fd, be.bstrerror());
1240 static bool solaris_archive_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent)
1243 int fd, filefd = -1, attrdirfd = -1;
1246 char current_xattr_namespace[PATH_MAX];
1247 bool retval = false;
1250 * Determine what argument to use. Use attr_parent when set
1251 * (recursive call) or jcr->last_fname for first call. Also save
1252 * the current depth of the xattr_space we are in.
1256 if (xattr_namespace)
1257 snprintf(current_xattr_namespace, sizeof(current_xattr_namespace), "%s%s/",
1258 xattr_namespace, attr_parent);
1260 strcpy(current_xattr_namespace, "/");
1262 name = jcr->last_fname;
1263 strcpy(current_xattr_namespace, "/");
1267 * Open the file on which to archive the xattrs read-only.
1269 if ((filefd = open(name, O_RDONLY | O_NONBLOCK)) < 0) {
1271 Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"),
1272 jcr->last_fname, be.bstrerror());
1273 Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1274 jcr->last_fname, be.bstrerror());
1280 * Open the xattr naming space.
1282 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1286 * Gentile way of the system saying this type of xattr layering is not supported.
1287 * Which is not problem we just forget about this this xattr.
1288 * But as this is not an error we return a positive return value.
1294 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1295 name, jcr->last_fname, be.bstrerror());
1296 Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1297 name, jcr->last_fname, be.bstrerror());
1304 * We need to change into the attribute directory to determine if each of the
1305 * attributes should be archived.
1307 if (fchdir(attrdirfd) < 0) {
1309 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1310 jcr->last_fname, be.bstrerror());
1311 Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1312 jcr->last_fname, attrdirfd, be.bstrerror());
1318 * Save the data of the toplevel xattr hidden_dir. We save this one before anything
1319 * else because the readdir returns "." entry after the extensible attr entry.
1320 * And as we want this entry before anything else we better just save its data.
1323 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, ".",
1324 true, STREAM_XATTR_SOLARIS);
1326 if ((fd = dup(attrdirfd)) == -1 ||
1327 (dirp = fdopendir(fd)) == (DIR *)NULL) {
1329 Jmsg2(jcr, M_ERROR, 0, _("Unable to list the xattr space on file \"%s\": ERR=%s\n"),
1330 jcr->last_fname, be.bstrerror());
1331 Dmsg3(100, "Unable to fdopendir xattr space on file \"%s\" using fd %d: ERR=%s\n",
1332 jcr->last_fname, fd, be.bstrerror());
1338 * Walk the namespace.
1340 while (dp = readdir(dirp)) {
1342 * Skip only the toplevel . dir.
1344 if (!attr_parent && !strcmp(dp->d_name, "."))
1348 * Skip all .. directories
1350 if (!strcmp(dp->d_name, ".."))
1353 Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
1354 current_xattr_namespace, dp->d_name, jcr->last_fname);
1356 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1358 * We are not interested in read-only extensible attributes.
1360 if (!strcmp(dp->d_name, VIEW_READONLY)) {
1361 Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
1362 current_xattr_namespace, dp->d_name, jcr->last_fname);
1368 * We are only interested in read-write extensible attributes
1369 * when they contain non-transient values.
1371 if (!strcmp(dp->d_name, VIEW_READWRITE)) {
1373 * Determine if there are non-transient system attributes at the toplevel.
1374 * We need to provide a fd to the open file.
1376 if (!solaris_has_non_transient_extensible_attributes(filefd)) {
1377 Dmsg3(400, "Skipping transient extensible attributes %s%s on file \"%s\"\n",
1378 current_xattr_namespace, dp->d_name, jcr->last_fname);
1384 * Archive the xattr.
1386 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1387 false, STREAM_XATTR_SOLARIS_SYS);
1390 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
1393 * Archive the xattr.
1395 solaris_archive_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1396 false, STREAM_XATTR_SOLARIS);
1403 if (attrdirfd != -1)
1412 static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, char *acl_text)
1414 #ifdef HAVE_EXTENDED_ACL
1418 if ((error = acl_fromtext(acl_text, &aclp)) != 0) {
1422 if ((fd != -1 && facl_set(fd, aclp) != 0) ||
1423 acl_set(attrname, aclp) != 0) {
1425 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1426 attrname, jcr->last_fname, be.bstrerror());
1427 Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1428 attrname, jcr->last_fname, be.bstrerror());
1437 #else /* HAVE_EXTENDED_ACL */
1439 aclent_t *acls = NULL;
1441 acls = aclfromtext(acl_text, &n);
1443 if ((fd != -1 && facl(fd, SETACL, n, acls) != 0) ||
1444 acl(attrname, SETACL, n, acls) != 0) {
1446 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1447 attrname, jcr->last_fname, be.bstrerror());
1448 Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1449 attrname, jcr->last_fname, be.bstrerror());
1459 #endif /* HAVE_EXTENDED_ACL */
1461 #endif /* HAVE_ACL */
1463 static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible)
1465 int fd, filefd = -1, attrdirfd = -1, attrfd = -1;
1466 int used_bytes, total_bytes, cnt;
1467 char *bp, *target_attrname, *attribs;
1468 char *linked_target = NULL;
1469 char *acl_text = NULL;
1473 struct timeval times[2];
1474 bool retval = false;
1477 * Parse the xattr stream. First the part that is the same for all xattrs.
1480 total_bytes = jcr->xattr_data_len;
1483 * The name of the target xattr has a leading / we are not interested
1484 * in that so skip it when decoding the string. We always start a the /
1485 * of the xattr space anyway.
1487 target_attrname = jcr->xattr_data + 1;
1488 if ((bp = strchr(target_attrname, '\0')) == (char *)NULL ||
1489 (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
1495 * Open the file on which to restore the xattrs read-only.
1497 if ((filefd = open(jcr->last_fname, O_RDONLY | O_NONBLOCK)) < 0) {
1499 Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"),
1500 jcr->last_fname, be.bstrerror());
1501 Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1502 jcr->last_fname, be.bstrerror());
1508 * Open the xattr naming space and make it the current working dir.
1510 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1512 Jmsg2(jcr, M_ERROR, 0, _("Unable to open xattr space on file \"%s\": ERR=%s\n"),
1513 jcr->last_fname, be.bstrerror());
1514 Dmsg2(100, "Unable to open xattr space on file \"%s\": ERR=%s\n",
1515 jcr->last_fname, be.bstrerror());
1520 if (fchdir(attrdirfd) < 0) {
1522 Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1523 jcr->last_fname, be.bstrerror());
1524 Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1525 jcr->last_fname, attrdirfd, be.bstrerror());
1531 * Try to open the correct xattr subdir based on the target_attrname given.
1532 * e.g. check if its a subdir attrname. Each / in the string makes us go
1535 while ((bp = strchr(target_attrname, '/')) != (char *)NULL) {
1538 if ((fd = open(target_attrname, O_RDONLY | O_NONBLOCK)) < 0) {
1540 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1541 target_attrname, jcr->last_fname, be.bstrerror());
1542 Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1543 target_attrname, jcr->last_fname, be.bstrerror());
1552 * Open the xattr naming space.
1554 if ((fd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1556 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1557 target_attrname, jcr->last_fname, be.bstrerror());
1558 Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1559 target_attrname, jcr->last_fname, be.bstrerror());
1568 * Make the xattr space our current workingdir.
1570 if (fchdir(attrdirfd) < 0) {
1572 Jmsg3(jcr, M_ERROR, 0, _("Unable to chdir to xattr space %s on file \"%s\": ERR=%s\n"),
1573 target_attrname, jcr->last_fname, be.bstrerror());
1574 Dmsg4(100, "Unable to fchdir to xattr space %s on file \"%s\" using fd %d: ERR=%s\n",
1575 target_attrname, jcr->last_fname, attrdirfd, be.bstrerror());
1580 target_attrname = ++bp;
1584 * Decode the attributes from the stream.
1586 decode_stat(attribs, &st, &inum);
1589 * Decode the next field (acl_text).
1591 if ((bp = strchr(attribs, '\0')) == (char *)NULL ||
1592 (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
1598 * Based on the filetype perform the correct action. We support most filetypes here, more
1599 * then the actual implementation on Solaris supports so some code may never get executed
1600 * due to limitations in the implementation.
1602 switch (st.st_mode & S_IFMT) {
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 (mkfifo(target_attrname, st.st_mode) < 0) {
1610 Jmsg3(jcr, M_ERROR, 0, _("Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n"),
1611 target_attrname, jcr->last_fname, be.bstrerror());
1612 Dmsg3(100, "Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n",
1613 target_attrname, jcr->last_fname, be.bstrerror());
1621 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1623 unlinkat(attrdirfd, target_attrname, 0);
1624 if (mknod(target_attrname, st.st_mode, st.st_rdev) < 0) {
1626 Jmsg3(jcr, M_ERROR, 0, _("Unable to mknod xattr %s on file \"%s\": ERR=%s\n"),
1627 target_attrname, jcr->last_fname, be.bstrerror());
1628 Dmsg3(100, "Unable to mknod xattr %s on file \"%s\": ERR=%s\n",
1629 target_attrname, jcr->last_fname, be.bstrerror());
1636 * If its not the hidden_dir create the entry.
1637 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1639 if (strcmp(target_attrname, ".")) {
1640 unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
1641 if (mkdir(target_attrname, st.st_mode) < 0) {
1643 Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
1644 target_attrname, jcr->last_fname, be.bstrerror());
1645 Dmsg3(100, "Unable to mkdir xattr %s on file \"%s\": ERR=%s\n",
1646 target_attrname, jcr->last_fname, be.bstrerror());
1654 * See if this is a hard linked file. e.g. inum != 0
1659 unlinkat(attrdirfd, target_attrname, 0);
1660 if (link(linked_target, target_attrname) < 0) {
1662 Jmsg4(jcr, M_ERROR, 0, _("Unable to link xattr %s to %s on file \"%s\": ERR=%s\n"),
1663 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1664 Dmsg4(100, "Unable to link xattr %s to %s on file \"%s\": ERR=%s\n",
1665 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1671 * Successfully restored xattr.
1676 if ((bp = strchr(acl_text, '\0')) == (char *)NULL ||
1677 (used_bytes = (bp - jcr->xattr_data)) >= total_bytes) {
1681 if (used_bytes < (total_bytes - 1))
1685 * Restore the actual xattr.
1687 if (!is_extensible) {
1688 unlinkat(attrdirfd, target_attrname, 0);
1691 if ((attrfd = openat(attrdirfd, target_attrname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) {
1693 Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1694 target_attrname, jcr->last_fname, be.bstrerror());
1695 Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1696 target_attrname, jcr->last_fname, be.bstrerror());
1703 * Restore the actual data.
1705 if (st.st_size > 0) {
1706 used_bytes = (data - jcr->xattr_data);
1707 cnt = total_bytes - used_bytes;
1710 * Do a sanity check, the st.st_size should be the same as the number of bytes
1711 * we have available as data of the stream.
1713 if (cnt != st.st_size) {
1714 Jmsg2(jcr, M_ERROR, 0, _("Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n"),
1715 target_attrname, jcr->last_fname);
1716 Dmsg2(100, "Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n",
1717 target_attrname, jcr->last_fname);
1723 cnt = write(attrfd, data, cnt);
1726 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore data of xattr %s on file \"%s\": ERR=%s\n"),
1727 target_attrname, jcr->last_fname, be.bstrerror());
1728 Dmsg3(100, "Unable to restore data of xattr %s on file \"%s\": ERR=%s\n",
1729 target_attrname, jcr->last_fname, be.bstrerror());
1736 cnt = total_bytes - used_bytes;
1742 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1746 if (symlink(linked_target, target_attrname) < 0) {
1748 Jmsg4(jcr, M_ERROR, 0, _("Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n"),
1749 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1750 Dmsg4(100, "Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n",
1751 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1757 * Successfully restored xattr.
1766 * Restore owner and acl for non extensible attributes.
1768 if (!is_extensible) {
1769 if (fchownat(attrdirfd, target_attrname, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW) < 0) {
1773 * Gentile way of the system saying this type of xattr layering is not supported.
1774 * But as this is not an error we return a positive return value.
1780 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n"),
1781 target_attrname, jcr->last_fname, be.bstrerror());
1782 Dmsg3(100, "Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n",
1783 target_attrname, jcr->last_fname, be.bstrerror());
1791 if (acl_text && *acl_text)
1792 if (!solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text))
1794 #endif /* HAVE_ACL */
1797 * For a non extensible attribute restore access and modification time on the xattr.
1799 if (!is_extensible) {
1800 times[0].tv_sec = st.st_atime;
1801 times[0].tv_usec = 0;
1802 times[1].tv_sec = st.st_mtime;
1803 times[1].tv_usec = 0;
1805 if (futimesat(attrdirfd, target_attrname, times) < 0) {
1807 Jmsg3(jcr, M_ERROR, 0, _("Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n"),
1808 target_attrname, jcr->last_fname, be.bstrerror());
1809 Dmsg3(100, "Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n",
1810 target_attrname, jcr->last_fname, be.bstrerror());
1817 * Successfully restored xattr.
1823 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n"),
1825 Dmsg1(100, "Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n",
1831 if (attrdirfd != -1)
1839 static bool solaris_extract_xattr(JCR *jcr, int stream)
1842 bool is_extensible = false;
1846 * First make sure we can restore xattr on the filesystem.
1849 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1850 case STREAM_XATTR_SOLARIS_SYS:
1851 if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
1852 Qmsg1(jcr, M_WARNING, 0,
1853 _("Failed to restore extensible attributes on file \"%s\"\n"),
1855 Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n",
1861 is_extensible = true;
1864 case STREAM_XATTR_SOLARIS:
1865 if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
1866 Qmsg1(jcr, M_WARNING, 0,
1867 _("Failed to restore extended attributes on file \"%s\"\n"),
1869 Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n",
1881 * As we change the cwd in the restore function save the current cwd
1882 * for restore after return from the solaris_restore_xattrs function.
1884 getcwd(cwd, sizeof(cwd));
1885 retval = solaris_restore_xattrs(jcr, is_extensible);
1891 static int solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1897 * First see if extended attributes or extensible attributes are present.
1898 * If not just pretend things went ok.
1900 if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) {
1904 * As we change the cwd in the archive function save the current cwd
1905 * for restore after return from the solaris_archive_xattrs function.
1907 getcwd(cwd, sizeof(cwd));
1908 retval = solaris_archive_xattrs(jcr, NULL, NULL);
1911 drop_xattr_link_cache();
1917 static bool solaris_parse_xattr_stream(JCR *jcr, int stream)
1920 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1921 case STREAM_XATTR_SOLARIS_SYS:
1923 case STREAM_XATTR_SOLARIS:
1924 return solaris_extract_xattr(jcr, stream);
1931 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1933 #if defined(HAVE_SUN_OS)
1934 return solaris_build_xattr_streams(jcr, ff_pkt);
1935 #elif defined(HAVE_DARWIN_OS)
1936 return darwin_build_xattr_streams(jcr, ff_pkt);
1937 #elif defined(HAVE_FREEBSD_OS)
1938 return freebsd_build_xattr_streams(jcr, ff_pkt);
1939 #elif defined(HAVE_LINUX_OS)
1940 return linux_build_xattr_streams(jcr, ff_pkt);
1941 #elif defined(HAVE_NETBSD_OS)
1942 return netbsd_build_xattr_streams(jcr, ff_pkt);
1946 bool parse_xattr_stream(JCR *jcr, int stream)
1949 * Based on the stream being passed in dispatch to the right function
1950 * for parsing and restoring a specific xattr. The platform determines
1951 * which streams are recognized and parsed and which are handled by
1952 * the default case and ignored. As only one of the platform defines
1953 * is true per compile we never end up with duplicate switch values.
1956 #if defined(HAVE_SUN_OS)
1957 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1958 case STREAM_XATTR_SOLARIS_SYS:
1960 case STREAM_XATTR_SOLARIS:
1961 return solaris_parse_xattr_stream(jcr, stream);
1962 #elif defined(HAVE_DARWIN_OS)
1963 case STREAM_XATTR_DARWIN:
1964 return darwin_parse_xattr_stream(jcr, stream);
1965 #elif defined(HAVE_FREEBSD_OS)
1966 case STREAM_XATTR_FREEBSD:
1967 return freebsd_parse_xattr_stream(jcr, stream);
1968 #elif defined(HAVE_LINUX_OS)
1969 case STREAM_XATTR_LINUX:
1970 return linux_parse_xattr_stream(jcr, stream);
1971 #elif defined(HAVE_NETBSD_OS)
1972 case STREAM_XATTR_NETBSD:
1973 return netbsd_parse_xattr_stream(jcr, stream);
1977 * Issue a warning and discard the message. But pretend the restore was ok.
1979 Qmsg2(jcr, M_WARNING, 0,
1980 _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
1981 jcr->last_fname, stream);
1983 } /* end switch (stream) */