]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/xattr.c
Add all acl and xattr related variables which are either global or already part of...
[bacula/bacula] / bacula / src / filed / xattr.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2008-2009 Free Software Foundation Europe e.V.
5
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
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  * Functions to handle Extended Attributes for bacula.
30  *
31  * Extended Attributes are so OS specific we only restore Extended Attributes if
32  * they were saved using a filed on the same platform.
33  *
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)
40  *
41  *   Written by Marco van Wieringen, November MMVIII
42  *
43  *   Version $Id$
44  */
45
46 #include "bacula.h"
47 #include "filed.h"
48
49 #if !defined(HAVE_XATTR)
50 /*
51  * Entry points when compiled without support for XATTRs or on an unsupported platform.
52  */
53 bxattr_exit_code build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
54 {
55    return bxattr_exit_fatal;
56 }
57
58 bxattr_exit_code parse_xattr_streams(JCR *jcr, int stream)
59 {
60    return bxattr_exit_fatal;
61 }
62 #else
63 /*
64  * Send a XATTR stream to the SD.
65  */
66 static bxattr_exit_code send_xattr_stream(JCR *jcr, int stream)
67 {
68    BSOCK *sd = jcr->store_bsock;
69    POOLMEM *msgsave;
70 #ifdef FD_NO_SEND_TEST
71    return bxattr_exit_ok;
72 #endif
73
74    /*
75     * Sanity check
76     */
77    if (jcr->xattr_data->content_length <= 0) {
78       return bxattr_exit_ok;
79    }
80
81    /*
82     * Send header
83     */
84    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
85       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
86             sd->bstrerror());
87       return bxattr_exit_fatal;
88    }
89
90    /*
91     * Send the buffer to the storage deamon
92     */
93    Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data->content);
94    msgsave = sd->msg;
95    sd->msg = jcr->xattr_data->content;
96    sd->msglen = jcr->xattr_data->content_length;
97    if (!sd->send()) {
98       sd->msg = msgsave;
99       sd->msglen = 0;
100       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
101             sd->bstrerror());
102       return bxattr_exit_fatal;
103    }
104
105    jcr->JobBytes += sd->msglen;
106    sd->msg = msgsave;
107    if (!sd->signal(BNET_EOD)) {
108       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
109             sd->bstrerror());
110       return bxattr_exit_fatal;
111    }
112    Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
113    return bxattr_exit_ok;
114 }
115
116 /*
117  * This is a supported OS, See what kind of interface we should use.
118  * Start with the generic interface used by most OS-es.
119  */
120 #if defined(HAVE_DARWIN_OS) || \
121     defined(HAVE_FREEBSD_OS) || \
122     defined(HAVE_LINUX_OS) || \
123     defined(HAVE_NETBSD_OS)
124        
125 #ifdef HAVE_SYS_XATTR_H
126 #include <sys/xattr.h>
127 #endif
128
129 /*
130  * Define the supported XATTR streams for this OS
131  */
132 #if defined(HAVE_DARWIN_OS)
133 static int os_default_xattr_streams[1] = { STREAM_XATTR_DARWIN };
134 #elif defined(HAVE_FREEBSD_OS)
135 static int os_default_xattr_streams[1] = { STREAM_XATTR_FREEBSD };
136 #elif defined(HAVE_LINUX_OS)
137 static int os_default_xattr_streams[1] = { STREAM_XATTR_LINUX };
138 #elif defined(HAVE_NETBSD_OS)
139 static int os_default_xattr_streams[1] = { STREAM_XATTR_NETBSD };
140 #endif
141
142 /*
143  * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
144  * listxattr, getxattr and setxattr with an extra options argument
145  * which mimics the l variants of the functions when we specify
146  * XATTR_NOFOLLOW as the options value.
147  */
148 #if defined(HAVE_DARWIN_OS)
149    #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
150    #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
151    #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
152 #else
153    /*
154     * Fallback to the non l-functions when those are not available.
155     */
156    #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
157    #define lgetxattr getxattr
158    #endif
159    #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
160    #define lsetxattr setxattr
161    #endif
162    #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
163    #define llistxattr listxattr
164    #endif
165 #endif
166
167 static void xattr_drop_internal_table(xattr_t *xattr_value_list)
168 {
169    xattr_t *current_xattr;
170
171    /*
172     * Walk the list of xattrs and free allocated memory on traversing.
173     */
174    for (current_xattr = xattr_value_list;
175         current_xattr != (xattr_t *)NULL;
176         current_xattr++) {
177       /*
178        * See if we can shortcut.
179        */
180       if (current_xattr->magic != XATTR_MAGIC)
181          break;
182
183       free(current_xattr->name);
184
185       if (current_xattr->value_length > 0)
186          free(current_xattr->value);
187    }
188
189    /*
190     * Free the array of control structs.
191     */
192    free(xattr_value_list);
193 }
194
195 /*
196  * The xattr stream for OSX, FreeBSD, Linux and NetBSD is a serialized stream of bytes
197  * which encodes one or more xattr_t structures.
198  *
199  * The Serialized stream consists of the following elements:
200  *    magic - A magic string which makes it easy to detect any binary incompatabilites
201  *    name_length - The length of the following xattr name
202  *    name - The name of the extended attribute
203  *    value_length - The length of the following xattr data
204  *    value - The actual content of the extended attribute
205  *
206  * This is repeated 1 or more times.
207  * 
208  */
209 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
210 {
211    xattr_t *current_xattr;
212    ser_declare;
213
214    /*
215     * Make sure the serialized stream fits in the poolmem buffer.
216     * We allocate some more to be sure the stream is gonna fit.
217     */
218    jcr->xattr_data->content = check_pool_memory_size(jcr->xattr_data->content, expected_serialize_len + 10);
219    ser_begin(jcr->xattr_data->content, expected_serialize_len + 10);
220
221    /*
222     * Walk the list of xattrs and serialize the data.
223     */
224    for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
225       /*
226        * See if we can shortcut.
227        */
228       if (current_xattr->magic != XATTR_MAGIC)
229          break;
230
231       ser_uint32(current_xattr->magic);
232       ser_uint32(current_xattr->name_length);
233       ser_bytes(current_xattr->name, current_xattr->name_length);
234
235       ser_uint32(current_xattr->value_length);
236       ser_bytes(current_xattr->value, current_xattr->value_length);
237    }
238
239    ser_end(jcr->xattr_data->content, expected_serialize_len + 10);
240    jcr->xattr_data->content_length = ser_length(jcr->xattr_data->content);
241    return jcr->xattr_data->content_length;
242 }
243
244 static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
245 {
246    int count = 0;
247    int32_t xattr_list_len,
248            xattr_value_len;
249    uint32_t expected_serialize_len = 0;
250    char *xattr_list, *bp;
251    xattr_t *xattr_value_list = NULL, *current_xattr;
252    bxattr_exit_code retval = bxattr_exit_error;
253    berrno be;
254
255    /*
256     * First get the length of the available list with extended attributes.
257     */
258    xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
259    if (xattr_list_len < 0) {
260       switch (errno) {
261       case ENOENT:
262          return bxattr_exit_ok;
263       default:
264          Mmsg2(jcr->errmsg, _("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());
268          return bxattr_exit_error;
269       }
270    } else if (xattr_list_len == 0) {
271       return bxattr_exit_ok;
272    }
273
274    /*
275     * Allocate room for the extented attribute list.
276     */
277    xattr_list = (char *)malloc(xattr_list_len + 1);
278    memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
279
280    /*
281     * Get the actual list of extended attributes names for a file.
282     */
283    xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
284    if (xattr_list_len < 0) {
285       switch (errno) {
286       case ENOENT:
287          retval = bxattr_exit_ok;
288          goto bail_out;
289       default:
290          Mmsg2(jcr->errmsg, _("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());
294          goto bail_out;
295       }
296    }
297    xattr_list[xattr_list_len] = '\0';
298
299    /*
300     * Count the number of extended attributes on a file.
301     */
302    bp = xattr_list;
303    while ((bp - xattr_list) + 1 < xattr_list_len) {
304 #if defined(HAVE_LINUX_OS)
305       /*
306        * On Linux you also get the acls in the extented attribute list.
307        * So we check if we are already backing up acls and if we do we
308        * don't store the extended attribute with the same info.
309        */
310       if ((ff_pkt->flags & FO_ACL) == 0 || strcmp(bp, "system.posix_acl_access"))
311          count++;
312 #else
313       count++;
314 #endif
315
316       bp = strchr(bp, '\0') + 1;
317    }
318
319    if (count == 0) {
320       retval = bxattr_exit_ok;
321       goto bail_out;
322    }
323
324    /*
325     * Allocate enough room to hold all extended attributes.
326     * After allocating the storage make sure its empty by zeroing it.
327     */
328    xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t));
329    memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
330
331    /*
332     * Walk the list of extended attributes names and retrieve the data.
333     * We already count the bytes needed for serializing the stream later on.
334     */
335    current_xattr = xattr_value_list;
336    bp = xattr_list;
337    while ((bp - xattr_list) + 1 < xattr_list_len) {
338 #if defined(HAVE_LINUX_OS)
339       /*
340        * On Linux you also get the acls in the extented attribute list.
341        * So we check if we are already backing up acls and if we do we
342        * don't store the extended attribute with the same info.
343        */
344       if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
345          bp = strchr(bp, '\0') + 1;
346          continue;
347       }
348 #endif
349
350       /*
351        * Each xattr valuepair starts with a magic so we can parse it easier.
352        */
353       current_xattr->magic = XATTR_MAGIC;
354       expected_serialize_len += sizeof(current_xattr->magic);
355
356       /*
357        * Allocate space for storing the name.
358        */
359       current_xattr->name_length = strlen(bp);
360       current_xattr->name = (char *)malloc(current_xattr->name_length);
361       memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
362
363       expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
364
365       /*
366        * First see how long the value is for the extended attribute.
367        */
368       xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
369       if (xattr_value_len < 0) {
370          switch (errno) {
371          case ENOENT:
372             retval = bxattr_exit_ok;
373             goto bail_out;
374          default:
375             Mmsg2(jcr->errmsg, _("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());
379             goto bail_out;
380          }
381       }
382
383       /*
384        * Allocate space for storing the value.
385        */
386       current_xattr->value = (char *)malloc(xattr_value_len);
387       memset((caddr_t)current_xattr->value, 0, xattr_value_len);
388
389       xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
390       if (xattr_value_len < 0) {
391          switch (errno) {
392          case ENOENT:
393             retval = bxattr_exit_ok;
394             goto bail_out;
395          default:
396             Mmsg2(jcr->errmsg, _("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());
400             goto bail_out;
401          }
402       }
403
404       /*
405        * Store the actual length of the value.
406        */
407       current_xattr->value_length = xattr_value_len;
408       expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
409
410       /*
411        * Protect ourself against things getting out of hand.
412        */
413       if (expected_serialize_len >= MAX_XATTR_STREAM) {
414          Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
415                jcr->last_fname, MAX_XATTR_STREAM);
416          goto bail_out;
417       }
418       
419       /*
420        * Next attribute.
421        */
422       current_xattr++;
423       bp = strchr(bp, '\0') + 1;
424    }
425
426    /*
427     * Serialize the datastream.
428     */
429    if (serialize_xattr_stream(jcr, expected_serialize_len, xattr_value_list) < expected_serialize_len) {
430       Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
431             jcr->last_fname);
432       Dmsg1(100, "Failed to serialize extended attributes on file \"%s\"\n",
433             jcr->last_fname);
434       goto bail_out;
435    }
436
437    xattr_drop_internal_table(xattr_value_list);
438    free(xattr_list);
439
440    /*
441     * Send the datastream to the SD.
442     */
443    return send_xattr_stream(jcr, os_default_xattr_streams[0]);
444
445 bail_out:
446    if (xattr_value_list) {
447       xattr_drop_internal_table(xattr_value_list);
448    }
449    free(xattr_list);
450    return retval;
451 }
452
453 static bxattr_exit_code generic_xattr_parse_streams(JCR *jcr, int stream)
454 {
455    unser_declare;
456    xattr_t current_xattr;
457    bxattr_exit_code retval = bxattr_exit_ok;
458    berrno be;
459
460    /*
461     * Parse the stream and perform the setxattr calls on the file.
462     *
463     * Start unserializing the data. We keep on looping while we have not
464     * unserialized all bytes in the stream.
465     */
466    unser_begin(jcr->xattr_data->content, jcr->xattr_data->content_length);
467    while (unser_length(jcr->xattr_data->content) < jcr->xattr_data->content_length) {
468       /*
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.
471        */
472       unser_uint32(current_xattr.magic);
473       if (current_xattr.magic != XATTR_MAGIC) {
474          Mmsg1(jcr->errmsg, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
475                jcr->last_fname);
476          Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
477                jcr->last_fname);
478          return bxattr_exit_error;
479       }
480
481       /*
482        * Decode the valuepair. First decode the length of the name.
483        */
484       unser_uint32(current_xattr.name_length);
485       
486       /*
487        * Allocate room for the name and decode its content.
488        */
489       current_xattr.name = (char *)malloc(current_xattr.name_length + 1);
490       unser_bytes(current_xattr.name, current_xattr.name_length);
491
492       /*
493        * The xattr_name needs to be null terminated for lsetxattr.
494        */
495       current_xattr.name[current_xattr.name_length] = '\0';
496
497       /*
498        * Decode the value length.
499        */
500       unser_uint32(current_xattr.value_length);
501
502       /*
503        * Allocate room for the value and decode its content.
504        */
505       current_xattr.value = (char *)malloc(current_xattr.value_length);
506       unser_bytes(current_xattr.value, current_xattr.value_length);
507
508       /*
509        * Try to set the extended attribute on the file.
510        * If we fail to set this attribute we flag the error but its not fatal,
511        * we try to restore the other extended attributes too.
512        */
513       if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
514                     current_xattr.value_length, 0) != 0) {
515          switch (errno) {
516          case ENOENT:
517             break;
518          default:
519             Mmsg2(jcr->errmsg, _("lsetxattr error on file \"%s\": ERR=%s\n"),
520                   jcr->last_fname, be.bstrerror());
521             Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
522                   jcr->last_fname, be.bstrerror());
523             retval = bxattr_exit_error;
524             break;
525          }
526       }
527
528       /*
529        * Free the temporary buffers.
530        */
531       free(current_xattr.name);
532       free(current_xattr.value);
533    }
534
535    unser_end(jcr->xattr_data->content, jcr->xattr_data->content_length);
536    return retval;
537 }
538
539 /*
540  * For all these os-es setup the build and parse function pointer to the generic functions.
541  */
542 static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = generic_xattr_build_streams;
543 static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = generic_xattr_parse_streams;
544
545 #elif defined(HAVE_SUN_OS)
546 /*
547  * Solaris extended attributes were introduced in Solaris 9
548  * by PSARC 1999/209
549  *
550  * Solaris extensible attributes were introduced in OpenSolaris
551  * by PSARC 2007/315 Solaris extensible attributes are also
552  * sometimes called extended system attributes.
553  *
554  * man fsattr(5) on Solaris gives a wealth of info. The most
555  * important bits are:
556  *
557  * Attributes are logically supported as files within the  file
558  * system.   The  file  system  is  therefore augmented with an
559  * orthogonal name space of file attributes. Any file  (includ-
560  * ing  attribute files) can have an arbitrarily deep attribute
561  * tree associated with it. Attribute values  are  accessed  by
562  * file descriptors obtained through a special attribute inter-
563  * face.  This logical view of "attributes as files" allows the
564  * leveraging  of  existing file system interface functionality
565  * to support the construction, deletion, and  manipulation  of
566  * attributes.
567  *
568  * The special files  "."  and  ".."  retain  their  accustomed
569  * semantics within the attribute hierarchy.  The "." attribute
570  * file refers to the current directory and the ".."  attribute
571  * file  refers to the parent directory.  The unnamed directory
572  * at the head of each attribute tree is considered the "child"
573  * of  the  file it is associated with and the ".." file refers
574  * to the associated file.  For  any  non-directory  file  with
575  * attributes,  the  ".." entry in the unnamed directory refers
576  * to a file that is not a directory.
577  *
578  * Conceptually, the attribute model is fully general. Extended
579  * attributes  can  be  any  type of file (doors, links, direc-
580  * tories, and so forth) and can even have their own attributes
581  * (fully  recursive).   As a result, the attributes associated
582  * with a file could be an arbitrarily deep directory hierarchy
583  * where each attribute could have an equally complex attribute
584  * tree associated with it.  Not all implementations  are  able
585  * to,  or  want to, support the full model. Implementation are
586  * therefore permitted to reject operations that are  not  sup-
587  * ported.   For  example,  the implementation for the UFS file
588  * system allows only regular files as attributes (for example,
589  * no sub-directories) and rejects attempts to place attributes
590  * on attributes.
591  *
592  * The following list details the operations that are  rejected
593  * in the current implementation:
594  *
595  * link                     Any attempt to create links between
596  *                          attribute  and  non-attribute space
597  *                          is rejected  to  prevent  security-
598  *                          related   or   otherwise  sensitive
599  *                          attributes from being exposed,  and
600  *                          therefore  manipulable,  as regular
601  *                          files.
602  *
603  * rename                   Any  attempt  to   rename   between
604  *                          attribute  and  non-attribute space
605  *                          is rejected to prevent  an  already
606  *                          linked  file from being renamed and
607  *                          thereby circumventing the link res-
608  *                          triction above.
609  *
610  * mkdir, symlink, mknod    Any  attempt  to  create  a   "non-
611  *                          regular" file in attribute space is
612  *                          rejected to reduce the  functional-
613  *                          ity,  and  therefore  exposure  and
614  *                          risk, of  the  initial  implementa-
615  *                          tion.
616  *
617  * The entire available name space has been allocated to  "gen-
618  * eral use" to bring the implementation in line with the NFSv4
619  * draft standard [NFSv4]. That standard defines "named  attri-
620  * butes"  (equivalent  to Solaris Extended Attributes) with no
621  * naming restrictions.  All Sun  applications  making  use  of
622  * opaque extended attributes will use the prefix "SUNW".
623  *
624  */
625 #ifdef HAVE_SYS_ATTR_H
626 #include <sys/attr.h>
627 #endif
628
629 #ifdef HAVE_ATTR_H
630 #include <attr.h>
631 #endif
632
633 #ifdef HAVE_SYS_NVPAIR_H
634 #include <sys/nvpair.h>
635 #endif
636
637 #ifdef HAVE_SYS_ACL_H
638 #include <sys/acl.h>
639 #endif
640
641 /*
642  * Define the supported XATTR streams for this OS
643  */
644 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
645 static int os_default_xattr_streams[2] = { STREAM_XATTR_SOLARIS, STREAM_XATTR_SOLARIS_SYS};
646 #else
647 static int os_default_xattr_streams[1] = { STREAM_XATTR_SOLARIS };
648 #endif /* defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) */
649
650 /*
651  * This code creates a temporary cache with entries for each xattr which has
652  * a link count > 1 (which indicates it has one or more hard linked counterpart(s))
653  */
654 static xattr_link_cache_entry_t *find_xattr_link_cache_entry(JCR *jcr, ino_t inum)
655 {
656    xattr_link_cache_entry_t *ptr;
657
658    foreach_alist(ptr, jcr->xattr_data->link_cache) {
659       if (ptr && ptr->inum == inum) {
660          return ptr;
661       }
662    }
663    return NULL;
664 }
665
666 static void add_xattr_link_cache_entry(JCR *jcr, ino_t inum, char *target)
667 {
668    xattr_link_cache_entry_t *ptr;
669
670    ptr = (xattr_link_cache_entry_t *)malloc(sizeof(xattr_link_cache_entry_t));
671    memset((caddr_t)ptr, 0, sizeof(xattr_link_cache_entry_t));
672    ptr->inum = inum;
673    bstrncpy(ptr->target, target, sizeof(ptr->target));
674    jcr->xattr_data->link_cache->append(ptr);
675 }
676
677 static void flush_xattr_link_cache(JCR *jcr)
678 {
679    xattr_link_cache_entry_t *ptr;
680
681    foreach_alist(ptr, jcr->xattr_data->link_cache) {
682       if (ptr && ptr->target) {
683          free(ptr->target);
684       }
685    }
686 >>>>>>> Add all acl and xattr related variables which are either global or already part of the JCR:bacula/src/filed/xattr.c
687 }
688
689 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
690 /*
691  * This function returns true if a non default extended system attribute
692  * list is associated with fd and returns false when an error has occured
693  * or when only extended system attributes other than archive,
694  * av_modified or crtime are set.
695  *
696  * The function returns true for the following cases:
697  *
698  * - any extended system attribute other than the default attributes
699  *   ('archive', 'av_modified' and 'crtime') is set
700  * - nvlist has NULL name string
701  * - nvpair has data type of 'nvlist'
702  * - default data type.
703  */
704 static bool solaris_has_non_transient_extensible_attributes(int fd)
705 {
706    boolean_t value;
707    data_type_t type;
708    nvlist_t *response;
709    nvpair_t *pair;
710    f_attr_t fattr;
711    char *name;
712    bool retval = false;
713
714    if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
715       return false;
716    }
717
718    pair = NULL;
719    while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
720       name = nvpair_name(pair);
721
722       if (name != NULL) {
723          fattr = name_to_attr(name);
724       } else {
725          retval = true;
726          goto bail_out;
727       }
728
729       type = nvpair_type(pair);
730       switch (type) {
731       case DATA_TYPE_BOOLEAN_VALUE:
732          if (nvpair_value_boolean_value(pair, &value) != 0) {
733             continue;
734          }
735          if (value && fattr != F_ARCHIVE &&
736                       fattr != F_AV_MODIFIED) {
737             retval = true;
738             goto bail_out;
739          }
740          break;
741       case DATA_TYPE_UINT64_ARRAY:
742          if (fattr != F_CRTIME) {
743             retval = true;
744             goto bail_out;
745          }
746          break;
747       case DATA_TYPE_NVLIST:
748       default:
749          retval = true;
750          goto bail_out;
751       }
752    }
753
754 bail_out:
755    if (response != NULL) {
756       nvlist_free(response);
757    }
758    return retval;
759 }
760 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
761
762 #if defined(HAVE_ACL) && !defined(HAVE_EXTENDED_ACL)
763 /*
764  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
765  * There is no need to store those acls as we already store the stat bits too.
766  */
767 static bool acl_is_trivial(int count, aclent_t *entries)
768 {
769    int n;
770    aclent_t *ace;
771
772    for (n = 0; n < count; n++) {
773       ace = &entries[n];
774       if (!(ace->a_type == USER_OBJ ||
775             ace->a_type == GROUP_OBJ ||
776             ace->a_type == OTHER_OBJ ||
777             ace->a_type == CLASS_OBJ))
778         return false;
779    }
780    return true;
781 }
782 #endif /* HAVE_ACL && !HAVE_EXTENDED_ACL */
783
784 static bxattr_exit_code solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text)
785 {
786 #ifdef HAVE_ACL
787 #ifdef HAVE_EXTENDED_ACL
788    int flags;
789    acl_t *aclp = NULL;
790    berrno be;
791
792    /*
793     * See if this attribute has an ACL
794     */
795    if ((fd != -1 && fpathconf(fd, _PC_ACL_ENABLED) > 0) ||
796        pathconf(attrname, _PC_ACL_ENABLED) > 0) {
797       /*
798        * See if there is a non trivial acl on the file.
799        */
800       if ((fd != -1 && facl_get(fd, ACL_NO_TRIVIAL, &aclp) != 0) ||
801            acl_get(attrname, ACL_NO_TRIVIAL, &aclp) != 0) {
802          switch (errno) {
803          case ENOENT:
804             return bxattr_exit_ok;
805          default:
806             Mmsg3(jcr->errmsg, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
807                   attrname, jcr->last_fname, be.bstrerror());
808             Dmsg3(100, "facl_get/acl_get of xattr %s on \"%s\" failed: ERR=%s\n",
809                   attrname, jcr->last_fname, be.bstrerror());
810             return bxattr_exit_error;
811          }
812       }
813
814       if (aclp != NULL) {
815 #if defined(ACL_SID_FMT)
816          /*
817           * New format flag added in newer Solaris versions.
818           */
819          flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
820 #else
821          flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
822 #endif /* ACL_SID_FMT */
823
824          *acl_text = acl_totext(aclp, flags);
825          acl_free(aclp);
826       } else {
827          *acl_text = NULL;
828       }
829    } else {
830       *acl_text = NULL;
831    }
832    return bxattr_exit_ok;
833 #else /* HAVE_EXTENDED_ACL */
834    int n;
835    aclent_t *acls = NULL;
836    berrno be;
837
838    /*
839     * See if this attribute has an ACL
840     */
841    if (fd != -1) {
842       n = facl(fd, GETACLCNT, 0, NULL);
843    } else {
844       n = acl(attrname, GETACLCNT, 0, NULL);
845    }
846
847    if (n >= MIN_ACL_ENTRIES) {
848       acls = (aclent_t *)malloc(n * sizeof(aclent_t));
849       if ((fd != -1 && facl(fd, GETACL, n, acls) != n) ||
850           acl(attrname, GETACL, n, acls) != n) {
851          switch (errno) {
852          case ENOENT:
853             free(acls);
854             return bxattr_exit_ok;
855          default:
856             Mmsg3(jcr->errmsg, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
857                   attrname, jcr->last_fname, be.bstrerror());
858             Dmsg3(100, "facl/acl of xattr %s on \"%s\" failed: ERR=%s\n",
859                   attrname, jcr->last_fname, be.bstrerror());
860             free(acls);
861             return bxattr_exit_error;
862          }
863       }
864
865       /*
866        * See if there is a non trivial acl on the file.
867        */
868       if (!acl_is_trivial(n, acls)) {
869          if ((*acl_text = acltotext(acls, n)) == NULL) {
870             Mmsg3(jcr->errmsg, _("Unable to get acl text on xattr %s on file \"%s\": ERR=%s\n"),
871                   attrname, jcr->last_fname, be.bstrerror());
872             Dmsg3(100, "acltotext of xattr %s on \"%s\" failed: ERR=%s\n",
873                   attrname, jcr->last_fname, be.bstrerror());
874             free(acls);
875             return bxattr_exit_error;
876          }
877       } else {
878          *acl_text = NULL;
879       }
880
881      free(acls);
882    } else {
883       *acl_text = NULL;
884    }
885    return bxattr_exit_ok;
886 #endif /* HAVE_EXTENDED_ACL */
887
888 #else /* HAVE_ACL */
889    return bxattr_exit_ok;
890 #endif /* HAVE_ACL */
891 }
892
893 /*
894  * Forward declaration for recursive function call.
895  */
896 static bxattr_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent);
897
898 /*
899  * Save an extended or extensible attribute.
900  * This is stored as an opaque stream of bytes with the following encoding:
901  *
902  * <xattr_name>\0<stat_buffer>\0<acl_string>\0<actual_xattr_data>
903  * 
904  * or for a hardlinked or symlinked attribute
905  *
906  * <xattr_name>\0<stat_buffer>\0<xattr_link_source>\0
907  *
908  * xattr_name can be a subpath relative to the file the xattr is on.
909  * stat_buffer is the string representation of the stat struct.
910  * acl_string is an acl text when a non trivial acl is set on the xattr.
911  * actual_xattr_data is the content of the xattr file.
912  */
913 static bxattr_exit_code solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace,
914                                            const char *attrname, bool toplevel_hidden_dir, int stream)
915 {
916    int cnt;
917    int attrfd = -1;
918    struct stat st;
919    xattr_link_cache_entry_t *xlce;
920    char target_attrname[PATH_MAX];
921    char link_source[PATH_MAX];
922    char *acl_text = NULL;
923    char attribs[MAXSTRING];
924    char buffer[BUFSIZ];
925    bxattr_exit_code retval = bxattr_exit_error;
926    berrno be;
927
928    bsnprintf(target_attrname, sizeof(target_attrname), "%s%s", xattr_namespace, attrname);
929
930    /*
931     * Get the stats of the extended or extensible attribute.
932     */
933    if (fstatat(fd, attrname, &st, AT_SYMLINK_NOFOLLOW) < 0) {
934       switch (errno) {
935       case ENOENT:
936          retval = bxattr_exit_ok;
937          goto bail_out;
938       default:
939          Mmsg3(jcr->errmsg, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"),
940                target_attrname, jcr->last_fname, be.bstrerror());
941          Dmsg3(100, "fstatat of xattr %s on \"%s\" failed: ERR=%s\n",
942                target_attrname, jcr->last_fname, be.bstrerror());
943          goto bail_out;
944       }
945    }
946
947    /*
948     * Based on the filetype perform the correct action. We support most filetypes here, more
949     * then the actual implementation on Solaris supports so some code may never get executed
950     * due to limitations in the implementation.
951     */
952    switch (st.st_mode & S_IFMT) {
953    case S_IFIFO:
954    case S_IFCHR:
955    case S_IFBLK:
956       /*
957        * Get any acl on the xattr.
958        */
959       if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bxattr_exit_ok)
960          goto bail_out;
961
962       /*
963        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
964        * Encode the stat struct into an ASCII representation.
965        */
966       encode_stat(attribs, &st, 0, stream);
967       cnt = bsnprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c",
968                      target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
969       break;
970
971    case S_IFDIR:
972       /*
973        * Get any acl on the xattr.
974        */
975       if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bxattr_exit_ok)
976          goto bail_out;
977
978       /*
979        * See if this is the toplevel_hidden_dir being saved.
980        */
981       if (toplevel_hidden_dir) {
982          /*
983           * Save the data for later storage when we encounter a real xattr. We store the data
984           * in the jcr->xattr_data->content buffer and flush that just before sending out the
985           * first real xattr. Encode the stat struct into an ASCII representation and jump
986           * out of the function.
987           */
988          encode_stat(attribs, &st, 0, stream);
989          cnt = bsnprintf(buffer, sizeof(buffer),
990                          "%s%c%s%c%s%c",
991                          target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
992          pm_memcpy(jcr->xattr_data->content, buffer, cnt);
993          jcr->xattr_data->content_length = cnt;
994          goto bail_out;
995       } else {
996          /*
997           * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
998           * Encode the stat struct into an ASCII representation.
999           */
1000          encode_stat(attribs, &st, 0, stream);
1001          cnt = bsnprintf(buffer, sizeof(buffer),
1002                          "%s%c%s%c%s%c",
1003                          target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1004       }
1005       break;
1006    case S_IFREG:
1007       /*
1008        * If this is a hardlinked file check the inode cache for a hit.
1009        */
1010       if (st.st_nlink > 1) {
1011          /*
1012           * See if the cache already knows this inode number.
1013           */
1014          if ((xlce = find_xattr_link_cache_entry(jcr, st.st_ino)) != NULL) {
1015             /*
1016              * Generate a xattr encoding with the reference to the target in there.
1017              */
1018             encode_stat(attribs, &st, st.st_ino, stream);
1019             cnt = bsnprintf(buffer, sizeof(buffer),
1020                             "%s%c%s%c%s%c",
1021                             target_attrname, 0, attribs, 0, xlce->target, 0);
1022             pm_memcpy(jcr->xattr_data->content, buffer, cnt);
1023             jcr->xattr_data->content_length = cnt;
1024             retval = send_xattr_stream(jcr, stream);
1025
1026             /*
1027              * For a hard linked file we are ready now, no need to recursively save the attributes.
1028              */
1029             goto bail_out;
1030          }
1031
1032          /*
1033           * Store this hard linked file in the cache.
1034           * Store the name relative to the top level xattr space.
1035           */
1036          add_xattr_link_cache_entry(jcr, st.st_ino, target_attrname + 1);
1037       }
1038
1039       /*
1040        * Get any acl on the xattr.
1041        */
1042       if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bxattr_exit_ok) {
1043          goto bail_out;
1044       }
1045
1046       /*
1047        * Encode the stat struct into an ASCII representation.
1048        */
1049       encode_stat(attribs, &st, 0, stream);
1050       cnt = bsnprintf(buffer, sizeof(buffer),
1051                      "%s%c%s%c%s%c",
1052                      target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
1053
1054       /*
1055        * Open the extended or extensible attribute file.
1056        */
1057       if ((attrfd = openat(fd, attrname, O_RDONLY)) < 0) {
1058          switch (errno) {
1059          case ENOENT:
1060             retval = bxattr_exit_ok;
1061             goto bail_out;
1062          default:
1063             Mmsg3(jcr->errmsg, _("Unable to open xattr %s on \"%s\": ERR=%s\n"),
1064                   target_attrname, jcr->last_fname, be.bstrerror());
1065             Dmsg3(100, "openat of xattr %s on \"%s\" failed: ERR=%s\n",
1066                   target_attrname, jcr->last_fname, be.bstrerror());
1067             goto bail_out;
1068          }
1069       }
1070       break;
1071
1072    case S_IFLNK:
1073       /*
1074        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1075        * Encode the stat struct into an ASCII representation.
1076        */
1077       if (readlink(attrname, link_source, sizeof(link_source)) < 0) {
1078          switch (errno) {
1079          case ENOENT:
1080             retval = bxattr_exit_ok;
1081             goto bail_out;
1082          default:
1083             Mmsg3(jcr->errmsg, _("Unable to read symlin %s on \"%s\": ERR=%s\n"),
1084                   target_attrname, jcr->last_fname, be.bstrerror());
1085             Dmsg3(100, "readlink of xattr %s on \"%s\" failed: ERR=%s\n",
1086                   target_attrname, jcr->last_fname, be.bstrerror());
1087             goto bail_out;
1088          }
1089       }
1090
1091       /*
1092        * Generate a xattr encoding with the reference to the target in there.
1093        */
1094       encode_stat(attribs, &st, st.st_ino, stream);
1095       cnt = bsnprintf(buffer, sizeof(buffer),
1096                       "%s%c%s%c%s%c",
1097                       target_attrname, 0, attribs, 0, link_source, 0);
1098       pm_memcpy(jcr->xattr_data->content, buffer, cnt);
1099       jcr->xattr_data->content_length = cnt;
1100       retval = send_xattr_stream(jcr, stream);
1101
1102       /*
1103        * For a soft linked file we are ready now, no need to recursively save the attributes.
1104        */
1105       goto bail_out;
1106
1107    default:
1108       goto bail_out;
1109    }
1110
1111    /*
1112     * See if this is the first real xattr being saved.
1113     * If it is save the toplevel_hidden_dir attributes first.
1114     * This is easy as its stored already in the jcr->xattr_data->content buffer.
1115     */
1116    if (jcr->xattr_data->nr_saved == 0) {
1117       retval = send_xattr_stream(jcr, STREAM_XATTR_SOLARIS);
1118       if (retval != bxattr_exit_ok) {
1119          goto bail_out;
1120       }
1121    }
1122
1123    pm_memcpy(jcr->xattr_data->content, buffer, cnt);
1124    jcr->xattr_data->content_length = cnt;
1125
1126    /*
1127     * Only dump the content of regular files.
1128     */
1129    switch (st.st_mode & S_IFMT) {
1130    case S_IFREG:
1131       if (st.st_size > 0) {
1132          /*
1133           * Protect ourself against things getting out of hand.
1134           */
1135          if (st.st_size >= MAX_XATTR_STREAM) {
1136             Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
1137                   jcr->last_fname, MAX_XATTR_STREAM);
1138             goto bail_out;
1139          }
1140
1141          while ((cnt = read(attrfd, buffer, sizeof(buffer))) > 0) {
1142             jcr->xattr_data->content = check_pool_memory_size(jcr->xattr_data->content, jcr->xattr_data->content_length + cnt);
1143             memcpy(jcr->xattr_data->content + jcr->xattr_data->content_length, buffer, cnt);
1144             jcr->xattr_data->content_length += cnt;
1145          }
1146
1147          if (cnt < 0) {
1148             Mmsg2(jcr->errmsg, _("Unable to read content of xattr %s on file \"%s\"\n"),
1149                   target_attrname, jcr->last_fname);
1150             Dmsg2(100, "read of data from xattr %s on \"%s\" failed\n",
1151                   target_attrname, jcr->last_fname);
1152             goto bail_out;
1153          }
1154       }
1155       break;
1156
1157    default:
1158       break;
1159    }
1160
1161    if (retval) {
1162       retval = send_xattr_stream(jcr, stream);
1163       jcr->xattr_data->nr_saved++;
1164    }
1165
1166    /*
1167     * Recursivly call solaris_save_extended_attributes for archiving the attributes
1168     * available on this extended attribute.
1169     */
1170    if (retval) {
1171       retval = solaris_save_xattrs(jcr, xattr_namespace, attrname);
1172       
1173       /*
1174        * The recursive call could change our working dir so change back to the wanted workdir.
1175        */
1176       if (fchdir(fd) < 0) {
1177          switch (errno) {
1178          case ENOENT:
1179             retval = bxattr_exit_ok;
1180             goto bail_out;
1181          default:
1182             Mmsg2(jcr->errmsg, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"),
1183                   jcr->last_fname, be.bstrerror());
1184             Dmsg3(100, "Unable to fchdir to xattr space of file \"%s\" using fd %d: ERR=%s\n",
1185                   jcr->last_fname, fd, be.bstrerror());
1186             goto bail_out;
1187          }
1188       }
1189    }
1190
1191 bail_out:
1192    if (acl_text) {
1193       free(acl_text);
1194    }
1195    if (attrfd != -1) {
1196       close(attrfd);
1197    }
1198    return retval;
1199 }
1200
1201 static bxattr_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent)
1202 {
1203    const char *name;
1204    int fd, filefd = -1, attrdirfd = -1;
1205    DIR *dirp;
1206    struct dirent *dp;
1207    char current_xattr_namespace[PATH_MAX];
1208    bxattr_exit_code retval = bxattr_exit_error;
1209    berrno be;
1210  
1211    /*
1212     * Determine what argument to use. Use attr_parent when set
1213     * (recursive call) or jcr->last_fname for first call. Also save
1214     * the current depth of the xattr_space we are in.
1215     */
1216    if (attr_parent) {
1217       name = attr_parent;
1218       if (xattr_namespace) {
1219          bsnprintf(current_xattr_namespace, sizeof(current_xattr_namespace), "%s%s/",
1220                    xattr_namespace, attr_parent);
1221       } else {
1222          bstrncpy(current_xattr_namespace, "/", sizeof(current_xattr_namespace));
1223       }
1224    } else {
1225       name = jcr->last_fname;
1226       bstrncpy(current_xattr_namespace, "/", sizeof(current_xattr_namespace));
1227    }
1228
1229    /*
1230     * Open the file on which to save the xattrs read-only.
1231     */
1232    if ((filefd = open(name, O_RDONLY | O_NONBLOCK)) < 0) {
1233       switch (errno) {
1234       case ENOENT:
1235          retval = bxattr_exit_ok;
1236          goto bail_out;
1237       default:
1238          Mmsg2(jcr->errmsg, _("Unable to open file \"%s\": ERR=%s\n"),
1239                jcr->last_fname, be.bstrerror());
1240          Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1241                jcr->last_fname, be.bstrerror());
1242          goto bail_out;
1243       }
1244    }
1245
1246    /*
1247     * Open the xattr naming space.
1248     */
1249    if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1250       switch (errno) {
1251       case EINVAL:
1252          /*
1253           * Gentile way of the system saying this type of xattr layering is not supported.
1254           * Which is not problem we just forget about this this xattr.
1255           * But as this is not an error we return a positive return value.
1256           */
1257          retval = bxattr_exit_ok;
1258          goto bail_out;
1259       case ENOENT:
1260          retval = bxattr_exit_ok;
1261          goto bail_out;
1262       default:
1263          Mmsg3(jcr->errmsg, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1264                name, jcr->last_fname, be.bstrerror());
1265          Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1266                name, jcr->last_fname, be.bstrerror());
1267          goto bail_out;
1268       }
1269    }
1270
1271   /*
1272    * We need to change into the attribute directory to determine if each of the
1273    * attributes should be saved.
1274    */
1275    if (fchdir(attrdirfd) < 0) {
1276       Mmsg2(jcr->errmsg, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1277             jcr->last_fname, be.bstrerror());
1278       Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1279             jcr->last_fname, attrdirfd, be.bstrerror());
1280       goto bail_out;
1281    }
1282
1283    /*
1284     * Save the data of the toplevel xattr hidden_dir. We save this one before anything
1285     * else because the readdir returns "." entry after the extensible attr entry.
1286     * And as we want this entry before anything else we better just save its data.
1287     */
1288    if (!attr_parent)
1289       solaris_save_xattr(jcr, attrdirfd, current_xattr_namespace, ".",
1290                          true, STREAM_XATTR_SOLARIS);
1291
1292    if ((fd = dup(attrdirfd)) == -1 ||
1293        (dirp = fdopendir(fd)) == (DIR *)NULL) {
1294       Mmsg2(jcr->errmsg, _("Unable to list the xattr space on file \"%s\": ERR=%s\n"),
1295             jcr->last_fname, be.bstrerror());
1296       Dmsg3(100, "Unable to fdopendir xattr space on file \"%s\" using fd %d: ERR=%s\n",
1297             jcr->last_fname, fd, be.bstrerror());
1298
1299       goto bail_out;
1300    }
1301
1302    /*
1303     * Walk the namespace.
1304     */
1305    while (dp = readdir(dirp)) {
1306       /*
1307        * Skip only the toplevel . dir.
1308        */
1309       if (!attr_parent && !strcmp(dp->d_name, "."))
1310          continue;
1311
1312       /*
1313        * Skip all .. directories
1314        */
1315       if (!strcmp(dp->d_name, ".."))
1316          continue;
1317
1318       Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
1319          current_xattr_namespace, dp->d_name, jcr->last_fname);
1320
1321 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1322       /*
1323        * We are not interested in read-only extensible attributes.
1324        */
1325       if (!strcmp(dp->d_name, VIEW_READONLY)) {
1326          Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
1327             current_xattr_namespace, dp->d_name, jcr->last_fname);
1328
1329          continue;
1330       }
1331
1332       /*
1333        * We are only interested in read-write extensible attributes
1334        * when they contain non-transient values.
1335        */
1336       if (!strcmp(dp->d_name, VIEW_READWRITE)) {
1337          /*
1338           * Determine if there are non-transient system attributes at the toplevel.
1339           * We need to provide a fd to the open file.
1340           */
1341          if (!solaris_has_non_transient_extensible_attributes(filefd)) {
1342             Dmsg3(400, "Skipping transient extensible attributes %s%s on file \"%s\"\n",
1343                current_xattr_namespace, dp->d_name, jcr->last_fname);
1344             continue;
1345          }
1346
1347          /*
1348           * Save the xattr.
1349           */
1350          solaris_save_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1351                             false, STREAM_XATTR_SOLARIS_SYS);
1352          continue;
1353       }
1354 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
1355
1356       /*
1357        * Save the xattr.
1358        */
1359       solaris_save_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
1360                          false, STREAM_XATTR_SOLARIS);
1361    }
1362
1363    closedir(dirp);
1364    retval = bxattr_exit_ok;
1365
1366 bail_out:
1367    if (attrdirfd != -1)
1368       close(attrdirfd);
1369    if (filefd != -1)
1370       close(filefd);
1371    return retval;
1372 }
1373
1374 #ifdef HAVE_ACL
1375 static bxattr_exit_code solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, char *acl_text)
1376 {
1377 #ifdef HAVE_EXTENDED_ACL
1378    int error;
1379    acl_t *aclp = NULL;
1380    berrno be;
1381
1382    if ((error = acl_fromtext(acl_text, &aclp)) != 0) {
1383       Mmsg1(jcr->errmsg, _("Unable to convert acl from text on file \"%s\"\n"),
1384             jcr->last_fname);
1385       return bxattr_exit_error;
1386    }
1387
1388    if ((fd != -1 && facl_set(fd, aclp) != 0) ||
1389         acl_set(attrname, aclp) != 0) {
1390       Mmsg3(jcr->errmsg, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1391             attrname, jcr->last_fname, be.bstrerror());
1392       Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1393             attrname, jcr->last_fname, be.bstrerror());
1394       return bxattr_exit_error;
1395    }
1396
1397    if (aclp) {
1398       acl_free(aclp);
1399    }
1400    return bxattr_exit_ok;
1401
1402 #else /* HAVE_EXTENDED_ACL */
1403    int n;
1404    aclent_t *acls = NULL;
1405    berrno be;
1406
1407    acls = aclfromtext(acl_text, &n);
1408    if (!acls) {
1409       if ((fd != -1 && facl(fd, SETACL, n, acls) != 0) ||
1410            acl(attrname, SETACL, n, acls) != 0) {
1411          Mmsg3(jcr->errmsg, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
1412                attrname, jcr->last_fname, be.bstrerror());
1413          Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n",
1414                attrname, jcr->last_fname, be.bstrerror());
1415          return bxattr_exit_error;
1416       }
1417    }
1418
1419    if (acls) {
1420       free(acls);
1421    }
1422    return bxattr_exit_ok;
1423
1424 #endif /* HAVE_EXTENDED_ACL */
1425
1426 }
1427 #endif /* HAVE_ACL */
1428
1429 static bxattr_exit_code solaris_restore_xattrs(JCR *jcr, bool is_extensible)
1430 {
1431    int fd, filefd = -1, attrdirfd = -1, attrfd = -1;
1432    int used_bytes, total_bytes, cnt;
1433    char *bp, *target_attrname, *attribs;
1434    char *linked_target = NULL;
1435    char *acl_text = NULL;
1436    char *data = NULL;
1437    int32_t inum;
1438    struct stat st;
1439    struct timeval times[2];
1440    bxattr_exit_code retval = bxattr_exit_error;
1441    berrno be;
1442
1443    /*
1444     * Parse the xattr stream. First the part that is the same for all xattrs.
1445     */
1446    used_bytes = 0;
1447    total_bytes = jcr->xattr_data->content_length;
1448
1449    /*
1450     * The name of the target xattr has a leading / we are not interested
1451     * in that so skip it when decoding the string. We always start a the /
1452     * of the xattr space anyway.
1453     */
1454    target_attrname = jcr->xattr_data->content + 1;
1455    if ((bp = strchr(target_attrname, '\0')) == (char *)NULL ||
1456        (used_bytes = (bp - jcr->xattr_data->content)) >= (total_bytes - 1)) {
1457       goto parse_error;
1458    }
1459    attribs = ++bp;
1460
1461    /*
1462     * Open the file on which to restore the xattrs read-only.
1463     */
1464    if ((filefd = open(jcr->last_fname, O_RDONLY | O_NONBLOCK)) < 0) {
1465       Mmsg2(jcr->errmsg, _("Unable to open file \"%s\": ERR=%s\n"),
1466             jcr->last_fname, be.bstrerror());
1467       Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n",
1468             jcr->last_fname, be.bstrerror());
1469       goto bail_out;
1470    }
1471
1472    /*
1473     * Open the xattr naming space and make it the current working dir.
1474     */
1475    if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1476       Mmsg2(jcr->errmsg, _("Unable to open xattr space on file \"%s\": ERR=%s\n"),
1477             jcr->last_fname, be.bstrerror());
1478       Dmsg2(100, "Unable to open xattr space on file \"%s\": ERR=%s\n",
1479             jcr->last_fname, be.bstrerror());
1480       goto bail_out;
1481    }
1482
1483    if (fchdir(attrdirfd) < 0) {
1484       Mmsg2(jcr->errmsg, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
1485             jcr->last_fname, be.bstrerror());
1486       Dmsg3(100, "Unable to fchdir to xattr space on file \"%s\" using fd %d: ERR=%s\n",
1487             jcr->last_fname, attrdirfd, be.bstrerror());
1488       goto bail_out;
1489    }
1490
1491    /*
1492     * Try to open the correct xattr subdir based on the target_attrname given.
1493     * e.g. check if its a subdir attrname. Each / in the string makes us go
1494     * one level deeper.
1495     */
1496    while ((bp = strchr(target_attrname, '/')) != (char *)NULL) {
1497       *bp = '\0';
1498
1499       if ((fd = open(target_attrname, O_RDONLY | O_NONBLOCK)) < 0) {
1500          Mmsg3(jcr->errmsg, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1501                target_attrname, jcr->last_fname, be.bstrerror());
1502          Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1503                target_attrname, jcr->last_fname, be.bstrerror());
1504          goto bail_out;
1505       }
1506
1507       close(filefd);
1508       filefd = fd;
1509
1510       /*
1511        * Open the xattr naming space.
1512        */
1513       if ((fd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
1514          Mmsg3(jcr->errmsg, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
1515                target_attrname, jcr->last_fname, be.bstrerror());
1516          Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n",
1517                target_attrname, jcr->last_fname, be.bstrerror());
1518          goto bail_out;
1519       }
1520
1521       close(attrdirfd);
1522       attrdirfd = fd;
1523
1524       /*
1525        * Make the xattr space our current workingdir.
1526        */
1527       if (fchdir(attrdirfd) < 0) {
1528          Mmsg3(jcr->errmsg, _("Unable to chdir to xattr space %s on file \"%s\": ERR=%s\n"),
1529                target_attrname, jcr->last_fname, be.bstrerror());
1530          Dmsg4(100, "Unable to fchdir to xattr space %s on file \"%s\" using fd %d: ERR=%s\n",
1531                target_attrname, jcr->last_fname, attrdirfd, be.bstrerror());
1532          goto bail_out;
1533       }
1534
1535       target_attrname = ++bp;
1536    }
1537
1538    /*
1539     * Decode the attributes from the stream.
1540     */
1541    decode_stat(attribs, &st, &inum);
1542
1543    /*
1544     * Decode the next field (acl_text).
1545     */
1546    if ((bp = strchr(attribs, '\0')) == (char *)NULL ||
1547        (used_bytes = (bp - jcr->xattr_data->content)) >= (total_bytes - 1)) {
1548       goto parse_error;
1549    }
1550    acl_text = ++bp;
1551
1552    /*
1553     * Based on the filetype perform the correct action. We support most filetypes here, more
1554     * then the actual implementation on Solaris supports so some code may never get executed
1555     * due to limitations in the implementation.
1556     */
1557    switch (st.st_mode & S_IFMT) {
1558    case S_IFIFO:
1559       /*
1560        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1561        */
1562       unlinkat(attrdirfd, target_attrname, 0);
1563       if (mkfifo(target_attrname, st.st_mode) < 0) {
1564          Mmsg3(jcr->errmsg, _("Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n"),
1565                target_attrname, jcr->last_fname, be.bstrerror());
1566          Dmsg3(100, "Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n",
1567                target_attrname,  jcr->last_fname, be.bstrerror());
1568          goto bail_out;
1569       }
1570       break;
1571    case S_IFCHR:
1572    case S_IFBLK:
1573       /*
1574        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1575        */
1576       unlinkat(attrdirfd, target_attrname, 0);
1577       if (mknod(target_attrname, st.st_mode, st.st_rdev) < 0) {
1578          Mmsg3(jcr->errmsg, _("Unable to mknod xattr %s on file \"%s\": ERR=%s\n"),
1579                target_attrname, jcr->last_fname, be.bstrerror());
1580          Dmsg3(100, "Unable to mknod xattr %s on file \"%s\": ERR=%s\n",
1581                target_attrname,  jcr->last_fname, be.bstrerror());
1582          goto bail_out;
1583       }
1584       break;
1585    case S_IFDIR:
1586       /*
1587        * If its not the hidden_dir create the entry.
1588        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1589        */
1590       if (strcmp(target_attrname, ".")) {
1591          unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
1592          if (mkdir(target_attrname, st.st_mode) < 0) {
1593             Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
1594                target_attrname, jcr->last_fname, be.bstrerror());
1595             Dmsg3(100, "Unable to mkdir xattr %s on file \"%s\": ERR=%s\n",
1596                target_attrname,  jcr->last_fname, be.bstrerror());
1597             goto bail_out;
1598          }
1599       }
1600       break;
1601    case S_IFREG:
1602       /*
1603        * See if this is a hard linked file. e.g. inum != 0
1604        */
1605       if (inum != 0) {
1606          linked_target = bp;
1607
1608          unlinkat(attrdirfd, target_attrname, 0);
1609          if (link(linked_target, target_attrname) < 0) {
1610             Mmsg4(jcr->errmsg, _("Unable to link xattr %s to %s on file \"%s\": ERR=%s\n"),
1611                   target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1612             Dmsg4(100, "Unable to link xattr %s to %s on file \"%s\": ERR=%s\n",
1613                   target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1614             goto bail_out;
1615          }
1616
1617          /*
1618           * Successfully restored xattr.
1619           */
1620          retval = bxattr_exit_ok;
1621          goto bail_out;
1622       } else {
1623          if ((bp = strchr(acl_text, '\0')) == (char *)NULL ||
1624              (used_bytes = (bp - jcr->xattr_data->content)) >= total_bytes) {
1625             goto parse_error;
1626          }
1627
1628          if (used_bytes < (total_bytes - 1))
1629             data = ++bp;
1630
1631          /*
1632           * Restore the actual xattr.
1633           */
1634          if (!is_extensible) {
1635             unlinkat(attrdirfd, target_attrname, 0);
1636          }
1637
1638          if ((attrfd = openat(attrdirfd, target_attrname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) {
1639             Mmsg3(jcr->errmsg, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
1640                   target_attrname, jcr->last_fname, be.bstrerror());
1641             Dmsg3(100, "Unable to open xattr %s on file \"%s\": ERR=%s\n",
1642                   target_attrname, jcr->last_fname, be.bstrerror());
1643             goto bail_out;
1644          }
1645       }
1646
1647       /*
1648        * Restore the actual data.
1649        */
1650       if (st.st_size > 0) {
1651          used_bytes = (data - jcr->xattr_data->content);
1652          cnt = total_bytes - used_bytes;
1653
1654          /*
1655           * Do a sanity check, the st.st_size should be the same as the number of bytes
1656           * we have available as data of the stream.
1657           */
1658          if (cnt != st.st_size) {
1659             Mmsg2(jcr->errmsg, _("Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n"),
1660                   target_attrname, jcr->last_fname);
1661             Dmsg2(100, "Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n",
1662                   target_attrname, jcr->last_fname);
1663             goto bail_out;
1664          }
1665
1666          while (cnt > 0) {
1667             cnt = write(attrfd, data, cnt);
1668             if (cnt < 0) {
1669                Mmsg3(jcr->errmsg, _("Unable to restore data of xattr %s on file \"%s\": ERR=%s\n"),
1670                      target_attrname, jcr->last_fname, be.bstrerror());
1671                Dmsg3(100, "Unable to restore data of xattr %s on file \"%s\": ERR=%s\n",
1672                      target_attrname, jcr->last_fname, be.bstrerror());
1673                goto bail_out;
1674             }
1675
1676             used_bytes += cnt;
1677             data += cnt;
1678             cnt = total_bytes - used_bytes;
1679          }
1680       }
1681       break;
1682    case S_IFLNK:
1683       /*
1684        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
1685        */
1686       linked_target = bp;
1687
1688       if (symlink(linked_target, target_attrname) < 0) {
1689          Mmsg4(jcr->errmsg, _("Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n"),
1690                target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1691          Dmsg4(100, "Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n",
1692                target_attrname, linked_target, jcr->last_fname, be.bstrerror());
1693          goto bail_out;
1694       }
1695
1696       /*
1697        * Successfully restored xattr.
1698        */
1699       retval = bxattr_exit_ok;
1700       goto bail_out;
1701    default:
1702       goto bail_out;
1703    }
1704
1705    /*
1706     * Restore owner and acl for non extensible attributes.
1707     */
1708    if (!is_extensible) {
1709       if (fchownat(attrdirfd, target_attrname, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW) < 0) {
1710          switch (errno) {
1711          case EINVAL:
1712             /*
1713              * Gentile way of the system saying this type of xattr layering is not supported.
1714              * But as this is not an error we return a positive return value.
1715              */
1716             retval = bxattr_exit_ok;
1717             break;
1718          case ENOENT:
1719             retval = bxattr_exit_ok;
1720             break;
1721          default:
1722             Mmsg3(jcr->errmsg, _("Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n"),
1723                   target_attrname, jcr->last_fname, be.bstrerror());
1724             Dmsg3(100, "Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n",
1725                   target_attrname, jcr->last_fname, be.bstrerror());
1726          }
1727          goto bail_out;
1728       }
1729    }
1730
1731 #ifdef HAVE_ACL
1732    if (acl_text && *acl_text)
1733       if (solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text) != bxattr_exit_ok)
1734          goto bail_out;
1735 #endif /* HAVE_ACL */
1736
1737    /*
1738     * For a non extensible attribute restore access and modification time on the xattr.
1739     */
1740    if (!is_extensible) {
1741       times[0].tv_sec = st.st_atime;
1742       times[0].tv_usec = 0;
1743       times[1].tv_sec = st.st_mtime;
1744       times[1].tv_usec = 0;
1745
1746       if (futimesat(attrdirfd, target_attrname, times) < 0) {
1747          Mmsg3(jcr->errmsg, _("Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n"),
1748                target_attrname, jcr->last_fname, be.bstrerror());
1749          Dmsg3(100, "Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n",
1750                target_attrname, jcr->last_fname, be.bstrerror());
1751          goto bail_out;
1752       }
1753    }
1754
1755    /*
1756     * Successfully restored xattr.
1757     */
1758    retval = bxattr_exit_ok;
1759    goto bail_out;
1760
1761 parse_error:
1762    Mmsg1(jcr->errmsg, _("Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n"),
1763          jcr->last_fname);
1764    Dmsg1(100, "Illegal xattr stream, failed to parse xattr stream on file \"%s\"\n",
1765          jcr->last_fname);
1766
1767 bail_out:
1768    if (attrfd != -1) {
1769       close(attrfd);
1770    }
1771    if (attrdirfd != -1) {
1772       close(attrdirfd);
1773    }
1774    if (filefd != -1) {
1775       close(filefd);
1776    }
1777    return retval;
1778 }
1779
1780 static bxattr_exit_code solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1781 {
1782    char cwd[PATH_MAX];
1783    bxattr_exit_code retval = bxattr_exit_ok;
1784
1785    /*
1786     * First see if extended attributes or extensible attributes are present.
1787     * If not just pretend things went ok.
1788     */
1789    if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) {
1790       jcr->xattr_data->nr_saved = 0;
1791
1792       /*
1793        * As we change the cwd in the save function save the current cwd
1794        * for restore after return from the solaris_save_xattrs function.
1795        */
1796       jcr->xattr_data->link_cache = New(alist(10, not_owned_by_alist));
1797       getcwd(cwd, sizeof(cwd));
1798       retval = solaris_save_xattrs(jcr, NULL, NULL);
1799       chdir(cwd);
1800       flush_xattr_link_cache(jcr);
1801       delete jcr->xattr_data->link_cache;
1802       jcr->xattr_data->link_cache = NULL;
1803    }
1804    return retval;
1805 }
1806
1807 static bxattr_exit_code solaris_parse_xattr_streams(JCR *jcr, int stream)
1808 {
1809    char cwd[PATH_MAX];
1810    bool is_extensible = false;
1811    bxattr_exit_code retval;
1812
1813    /*
1814     * First make sure we can restore xattr on the filesystem.
1815     */
1816    switch (stream) {
1817 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
1818    case STREAM_XATTR_SOLARIS_SYS:
1819       if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
1820          Qmsg1(jcr, M_WARNING, 0,
1821                _("Failed to restore extensible attributes on file \"%s\"\n"),
1822                jcr->last_fname);
1823          Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n",
1824             jcr->last_fname);
1825          return bxattr_exit_error;
1826       }
1827
1828       is_extensible = true;
1829       break;
1830 #endif
1831    case STREAM_XATTR_SOLARIS:
1832       if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
1833          Qmsg1(jcr, M_WARNING, 0,
1834                _("Failed to restore extended attributes on file \"%s\"\n"),
1835                jcr->last_fname);
1836          Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n",
1837             jcr->last_fname);
1838          return bxattr_exit_error;
1839       }
1840       break;
1841    default:
1842       return bxattr_exit_error;
1843    }
1844
1845    /*
1846     * As we change the cwd in the restore function save the current cwd
1847     * for restore after return from the solaris_restore_xattrs function.
1848     */
1849    getcwd(cwd, sizeof(cwd));
1850    retval = solaris_restore_xattrs(jcr, is_extensible);
1851    chdir(cwd);
1852    return retval;
1853 }
1854
1855
1856 /*
1857  * Function pointers to the build and parse function to use for these xattrs.
1858  */
1859 static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = solaris_build_xattr_streams;
1860 static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = solaris_parse_xattr_streams;
1861
1862 #endif /* defined(HAVE_SUN_OS) */
1863
1864 /*
1865  * Entry points when compiled with support for XATTRs on a supported platform.
1866  */
1867 bxattr_exit_code build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1868 {
1869    if (os_build_xattr_streams) {
1870       return (*os_build_xattr_streams)(jcr, ff_pkt);
1871    }
1872    return bxattr_exit_error;
1873 }
1874
1875 bxattr_exit_code parse_xattr_streams(JCR *jcr, int stream)
1876 {
1877    unsigned int cnt;
1878
1879    if (os_parse_xattr_streams) {
1880       /*
1881        * See if we can parse this stream, and ifso give it a try.
1882        */
1883       for (cnt = 0; cnt < sizeof(os_default_xattr_streams) / sizeof(int); cnt++) {
1884          if (os_default_xattr_streams[cnt] == stream) {
1885             return (*os_parse_xattr_streams)(jcr, stream);
1886          }
1887       }
1888    }
1889    /*
1890     * Issue a warning and discard the message. But pretend the restore was ok.
1891     */
1892    Jmsg2(jcr, M_WARNING, 0,
1893       _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
1894       jcr->last_fname, stream);
1895    return bxattr_exit_error;
1896 }
1897 #endif