]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/acl.c
Fixed two typos while implementing new Solaris xattr code.
[bacula/bacula] / bacula / src / filed / acl.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2004-2008 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 ACLs for bacula.
30  *
31  * We handle two different types of ACLs: access and default ACLS.
32  * On most systems that support default ACLs they only apply to directories.
33  *
34  * On some systems (eg. linux and FreeBSD) we must obtain the two ACLs
35  * independently, while others (eg. Solaris) provide both in one call.
36  *
37  * The Filed saves ACLs in their native format and uses different streams
38  * for all different platforms. Currently we only allow ACLs to be restored
39  * which were saved in the native format of the platform they are extracted
40  * on. Later on we might add conversion functions for mapping from one
41  * platform to an other or allow restores of systems that use the same
42  * native format.
43  *
44  * Its also interesting to see what the exact format of acl text is on
45  * certain platforms and if they use they same encoding we might allow
46  * different platform streams to be decoded on an other similar platform.
47  * As we implement the decoding/restoring process as a big switch based
48  * on the stream number being passed in extending the switching code is
49  * easy.
50  *
51  *   Original written by Preben 'Peppe' Guldberg, December MMIV
52  *   Major rewrite by Marco van Wieringen, November MMVIII
53  *
54  *   Version $Id$
55  */
56   
57 #include "bacula.h"
58 #include "filed.h"
59   
60 /*
61  * List of supported OSs. Everything outside that gets stub functions.
62  * Also when ACL support is explicitly disabled.
63  * Not sure if all the HAVE_XYZ_OS are correct for autoconf.
64  * The ones that says man page, are coded according to man pages only.
65  */
66 #if !defined(HAVE_ACL)              /* ACL support is required, of course */ \
67    || !( defined(HAVE_AIX_OS)       /* man page -- may need flags         */ \
68       || defined(HAVE_DARWIN_OS)    /* tested   -- compile without flags  */ \
69       || defined(HAVE_FREEBSD_OS)   /* tested   -- compile without flags  */ \
70       || defined(HAVE_HPUX_OS)      /* man page -- may need flags         */ \
71       || defined(HAVE_IRIX_OS)      /* man page -- compile without flags  */ \
72       || defined(HAVE_LINUX_OS)     /* tested   -- compile with -lacl     */ \
73       || defined(HAVE_OSF1_OS)      /* man page -- may need -lpacl        */ \
74       || defined(HAVE_SUN_OS)       /* tested   -- compile with -lsec     */ \
75        )
76
77 /*
78  * Entry points when compiled without support for ACLs or on an unsupported platform.
79  */
80 bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
81 {
82    Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
83    return false;
84 }
85
86 bool parse_acl_stream(JCR *jcr, int stream)
87 {
88    Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
89    return false;
90 }
91
92 #else
93
94 /*
95  * Send an ACL stream to the SD.
96  */
97 static bool send_acl_stream(JCR *jcr, int stream, int len)
98 {
99    BSOCK *sd = jcr->store_bsock;
100    POOLMEM *msgsave;
101 #ifdef FD_NO_SEND_TEST
102    return true;
103 #endif
104
105    /*
106     * Send header
107     */
108    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
109       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
110             sd->bstrerror());
111
112       return false;
113    }
114
115    /*
116     * Send the buffer to the storage deamon
117     */
118    Dmsg1(400, "Backing up ACL <%s>\n", jcr->acl_data);
119    msgsave = sd->msg;
120    sd->msg = jcr->acl_data;
121    sd->msglen = len + 1;
122    if (!sd->send()) {
123       sd->msg = msgsave;
124       sd->msglen = 0;
125       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
126             sd->bstrerror());
127
128       return false;
129    }
130
131    jcr->JobBytes += sd->msglen;
132    sd->msg = msgsave;
133    if (!sd->signal(BNET_EOD)) {
134       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
135             sd->bstrerror());
136
137       return false;
138    }
139
140    Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
141
142    return true;
143 }
144
145 #if defined(HAVE_AIX_OS)
146
147 #include <sys/access.h>
148
149 static bool aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
150 {
151    char *acl_text;
152    int len;
153
154    if ((acl_text = acl_get(jcr->last_fname)) != NULL) {
155       len = pm_strcpy(jcr->acl_data, acl_text);
156       actuallyfree(acl_text);
157
158       return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT, len);
159    }
160
161    return false;
162 }
163
164 static bool aix_parse_acl_stream(JCR *jcr, int stream)
165 {
166    if (acl_put(jcr->last_fname, jcr->acl_data, 0) != 0) {
167       return false;
168    }
169
170    return true;
171 }
172
173 #elif defined(HAVE_DARWIN_OS) \
174    || defined(HAVE_FREEBSD_OS) \
175    || defined(HAVE_IRIX_OS) \
176    || defined(HAVE_OSF1_OS) \
177    || defined(HAVE_LINUX_OS)
178
179 #include <sys/types.h>
180
181 #ifdef HAVE_SYS_ACL_H
182 #include <sys/acl.h>
183 #else
184 #error "configure failed to detect availability of sys/acl.h"
185 #endif
186
187 /* On IRIX we can get shortened ACLs */
188 #if defined(HAVE_IRIX_OS) && defined(BACL_WANT_SHORT_ACLS)
189 #define acl_to_text(acl,len)     acl_to_short_text((acl), (len))
190 #endif
191
192 /* In Linux we can get numeric and/or shorted ACLs */
193 #if defined(HAVE_LINUX_OS)
194 #if defined(BACL_WANT_SHORT_ACLS) && defined(BACL_WANT_NUMERIC_IDS)
195 #define BACL_ALTERNATE_TEXT            (TEXT_ABBREVIATE|TEXT_NUMERIC_IDS)
196 #elif defined(BACL_WANT_SHORT_ACLS)
197 #define BACL_ALTERNATE_TEXT            TEXT_ABBREVIATE
198 #elif defined(BACL_WANT_NUMERIC_IDS)
199 #define BACL_ALTERNATE_TEXT            TEXT_NUMERIC_IDS
200 #endif
201 #ifdef BACL_ALTERNATE_TEXT
202 #include <acl/libacl.h>
203 #define acl_to_text(acl,len)     (acl_to_any_text((acl), NULL, ',', BACL_ALTERNATE_TEXT))
204 #endif
205 #endif
206
207 /*
208  * Some generic functions used by multiple OSes.
209  */
210 static acl_type_t bac_to_os_acltype(bacl_type acltype)
211 {
212    acl_type_t ostype;
213
214    switch (acltype) {
215    case BACL_TYPE_ACCESS:
216       ostype = ACL_TYPE_ACCESS;
217       break;
218    case BACL_TYPE_DEFAULT:
219       ostype = ACL_TYPE_DEFAULT;
220       break;
221
222 #ifdef ACL_TYPE_DEFAULT_DIR
223    case BACL_TYPE_DEFAULT_DIR:
224       /*
225        * OSF1 has an additional acl type named ACL_TYPE_DEFAULT_DIR.
226        */
227       ostype = ACL_TYPE_DEFAULT_DIR;
228       break;
229 #endif
230 #ifdef ACL_TYPE_EXTENDED
231    case BACL_TYPE_EXTENDED:
232       /*
233        * MacOSX has an additional acl type named ACL_TYPE_EXTENDED.
234        */
235       ostype = ACL_TYPE_EXTENDED;
236       break;
237 #endif
238    default:
239       /*
240        * This should never happen, as the per os version function only tries acl
241        * types supported on a certain platform.
242        */
243       ostype = (acl_type_t)ACL_TYPE_NONE;
244       break;
245    }
246
247    return ostype;
248 }
249
250 #if !defined(HAVE_DARWIN_OS)
251 /*
252  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
253  * There is no need to store those acls as we already store the stat bits too.
254  */
255 static bool acl_is_trivial(acl_t acl)
256 {
257   /*
258    * acl is trivial if it has only the following entries:
259    * "user::",
260    * "group::",
261    * "other::"
262    */
263    acl_entry_t ace;
264    acl_tag_t tag;
265 #if defined(HAVE_FREEBSD_OS) || defined(HAVE_LINUX_OS)
266    int entry_available;
267
268    entry_available = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace);
269    while (entry_available == 1) {
270       /*
271        * Get the tag type of this acl entry.
272        * If we fail to get the tagtype we call the acl non-trivial.
273        */
274       if (acl_get_tag_type(ace, &tag) < 0)
275          return false;
276
277       /*
278        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
279        */
280       if (tag != ACL_USER_OBJ &&
281           tag != ACL_GROUP_OBJ &&
282           tag != ACL_OTHER)
283          return false;
284
285       entry_available = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace);
286    }
287
288    return true;
289 #elif defined(HAVE_IRIX_OS)
290    int n;
291
292    for (n = 0; n < acl->acl_cnt; n++) {
293       ace = &acl->acl_entry[n];
294       tag = ace->ae_tag;
295
296       /*
297        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
298        */
299       if (tag != ACL_USER_OBJ &&
300           tag != ACL_GROUP_OBJ &&
301           tag != ACL_OTHER)
302          return false;
303    }
304
305    return true;
306 #elif defined(HAVE_OSF1_OS)
307    int count;
308
309    ace = acl->acl_first;
310    count = acl->acl_num;
311
312    while (count > 0) {
313       tag = ace->entry->acl_type;
314
315       /*
316        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
317        */
318       if (tag != ACL_USER_OBJ &&
319           tag != ACL_GROUP_OBJ &&
320           tag != ACL_OTHER)
321          return false;
322
323       /*
324        * On Tru64, perm can also contain non-standard bits such as
325        * PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ...
326        */
327       if ((ace->entry->acl_perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)))
328          return false;
329
330       ace = ace->next;
331       count--;
332    }
333
334    return true;
335 #endif
336 }
337 #endif
338
339 /*
340  * Generic wrapper around acl_get_file call.
341  */
342 static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
343 {
344    acl_t acl;
345    int len;
346    acl_type_t ostype;
347    char *acl_text;
348
349    ostype = bac_to_os_acltype(acltype);
350    acl = acl_get_file(jcr->last_fname, ostype);
351    if (acl) {
352 #if defined(HAVE_IRIX_OS)
353       /* 
354        * From observation, IRIX's acl_get_file() seems to return a
355        * non-NULL acl with a count field of -1 when a file has no ACL
356        * defined, while IRIX's acl_to_text() returns NULL when presented
357        * with such an ACL. 
358        *
359        * Checking the count in the acl structure before calling
360        * acl_to_text() lets us avoid error messages about files
361        * with no ACLs, without modifying the flow of the code used for 
362        * other operating systems, and it saves making some calls
363        * to acl_to_text() besides.
364        */
365       if (acl->acl_cnt <= 0) {
366          pm_strcpy(jcr->acl_data, "");
367          acl_free(acl);
368          return 0;
369       }
370 #endif
371
372 #if !defined(HAVE_DARWIN_OS)
373       /*
374        * Make sure this is not just a trivial ACL.
375        */
376       if (acltype == BACL_TYPE_ACCESS && acl_is_trivial(acl)) {
377          /*
378           * The ACLs simply reflect the (already known) standard permissions
379           * So we don't send an ACL stream to the SD.
380           */
381          pm_strcpy(jcr->acl_data, "");
382          acl_free(acl);
383          return 0;
384       }
385 #endif
386
387       if ((acl_text = acl_to_text(acl, NULL)) != NULL) {
388          len = pm_strcpy(jcr->acl_data, acl_text);
389          acl_free(acl);
390          acl_free(acl_text);
391
392          return len;
393       }
394
395       berrno be;
396       Jmsg2(jcr, M_ERROR, 0, _("acl_to_text error on file \"%s\": ERR=%s\n"),
397          jcr->last_fname, be.bstrerror());
398       Dmsg2(100, "acl_to_text error file=%s ERR=%s\n",  
399          jcr->last_fname, be.bstrerror());
400
401       pm_strcpy(jcr->acl_data, "");
402       acl_free(acl);
403
404       return -1;
405    }
406
407    /*
408     * Handle errors gracefully.
409     */
410    switch (errno) {
411 #if defined(BACL_ENOTSUP)
412    case BACL_ENOTSUP:
413       /*
414        * Not supported, just pretend there is nothing to see
415        */
416       pm_strcpy(jcr->acl_data, "");
417       return 0;
418 #endif
419    default:
420       berrno be;
421       Jmsg2(jcr, M_ERROR, 0, _("acl_get_file error on file \"%s\": ERR=%s\n"),
422          jcr->last_fname, be.bstrerror());
423       Dmsg2(100, "acl_get_file error file=%s ERR=%s\n",  
424          jcr->last_fname, be.bstrerror());
425
426       pm_strcpy(jcr->acl_data, "");
427       return -1;
428    }
429 }
430
431 /*
432  * Generic wrapper around acl_set_file call.
433  */
434 static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype)
435 {
436    acl_t acl;
437    acl_type_t ostype;
438
439    /*
440     * If we get empty default ACLs, clear ACLs now
441     */
442    ostype = bac_to_os_acltype(acltype);
443    if (ostype == ACL_TYPE_DEFAULT && strlen(jcr->acl_data) == 0) {
444       if (acl_delete_def_file(jcr->last_fname) == 0) {
445          return true;
446       }
447       berrno be;
448       Jmsg2(jcr, M_ERROR, 0, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"),
449          jcr->last_fname, be.bstrerror());
450
451       return false;
452    }
453
454    acl = acl_from_text(jcr->acl_data);
455    if (acl == NULL) {
456       berrno be;
457       Jmsg2(jcr, M_ERROR, 0, _("acl_from_text error on file \"%s\": ERR=%s\n"),
458          jcr->last_fname, be.bstrerror());
459       Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n",  
460          jcr->acl_data, jcr->last_fname, be.bstrerror());
461
462       return false;
463    }
464
465    /*
466     * FreeBSD always fails acl_valid() - at least on valid input...
467     * As it does the right thing, given valid input, just ignore acl_valid().
468     */
469 #ifndef HAVE_FREEBSD_OS
470    if (acl_valid(acl) != 0) {
471       berrno be;
472       Jmsg2(jcr, M_ERROR, 0, _("ac_valid error on file \"%s\": ERR=%s\n"),
473          jcr->last_fname, be.bstrerror());
474       Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n",  
475          jcr->acl_data, jcr->last_fname, be.bstrerror());
476       acl_free(acl);
477
478       return false;
479    }
480 #endif
481
482    /*
483     * Restore the ACLs, but don't complain about links which really should
484     * not have attributes, and the file it is linked to may not yet be restored.
485     * This is only true for the old acl streams as in the new implementation we
486     * don't save acls of symlinks (which cannot have acls anyhow)
487     */
488    if (acl_set_file(jcr->last_fname, ostype, acl) != 0 && jcr->last_type != FT_LNK) {
489       berrno be;
490       Jmsg2(jcr, M_ERROR, 0, _("acl_set_file error on file \"%s\": ERR=%s\n"),
491          jcr->last_fname, be.bstrerror());
492       Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n",  
493          jcr->acl_data, jcr->last_fname, be.bstrerror());
494       acl_free(acl);
495
496       return false;
497    }
498    acl_free(acl);
499
500    return true;
501 }
502
503 /*
504  * OS specific functions for handling different types of acl streams.
505  */
506 #if defined(HAVE_DARWIN_OS)
507 static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
508 {
509    int len;
510
511 #if defined(ACL_TYPE_EXTENDED)
512    /*
513     * On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
514     * and acl_get_file (name, ACL_TYPE_DEFAULT)
515     * always return NULL / EINVAL.  There is no point in making
516     * these two useless calls.  The real ACL is retrieved through
517     * acl_get_file (name, ACL_TYPE_EXTENDED).
518     *
519     * Read access ACLs for files, dirs and links
520     */
521    if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0)
522       return false;
523 #else
524    /*
525     * Read access ACLs for files, dirs and links
526     */
527    if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
528       return false;
529
530    if (len > 0) {
531       if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL, len))
532          return false;
533    }
534 #endif
535
536    return true;
537 }
538
539 static bool darwin_parse_acl_stream(JCR *jcr, int stream)
540 {
541    switch (stream) {
542    case STREAM_UNIX_ACCESS_ACL:
543    case STREAM_ACL_DARWIN_ACCESS_ACL:
544       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
545    }
546
547    return false;
548 }
549 #elif defined(HAVE_FREEBSD_OS)
550 static bool freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
551 {
552    int len;
553
554    /*
555     * Read access ACLs for files, dirs and links
556     */
557    if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
558       return false;
559
560    if (len > 0) {
561       if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_ACCESS_ACL, len))
562          return false;
563    }
564
565    /*
566     * Directories can have default ACLs too
567     */
568    if (ff_pkt->type == FT_DIREND) {
569       if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
570          return false;
571
572       if (len > 0) {
573          if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_DEFAULT_ACL, len))
574             return false;
575       }
576    }
577
578    return true;
579 }
580
581 static bool freebsd_parse_acl_stream(JCR *jcr, int stream)
582 {
583    switch (stream) {
584    case STREAM_UNIX_ACCESS_ACL:
585    case STREAM_ACL_FREEBSD_ACCESS_ACL:
586       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
587    case STREAM_UNIX_DEFAULT_ACL:
588    case STREAM_ACL_FREEBSD_DEFAULT_ACL:
589       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
590    }
591
592    return false;
593 }
594 #elif defined(HAVE_IRIX_OS)
595 static bool irix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
596 {
597    int len;
598
599    /*
600     * Read access ACLs for files, dirs and links
601     */
602    if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
603       return false;
604
605    if (len > 0) {
606       if (!send_acl_stream(jcr, STREAM_ACL_IRIX_ACCESS_ACL, len))
607          return false;
608    }
609
610    /*
611     * Directories can have default ACLs too
612     */
613    if (ff_pkt->type == FT_DIREND) {
614       if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
615          return false;
616
617       if (len > 0) {
618          if (!send_acl_stream(jcr, STREAM_ACL_IRIX_DEFAULT_ACL, len))
619             return false;
620       }
621    }
622
623    return true;
624 }
625
626 static bool irix_parse_acl_stream(JCR *jcr, int stream)
627 {
628    switch (stream) {
629    case STREAM_UNIX_ACCESS_ACL:
630    case STREAM_ACL_IRIX_ACCESS_ACL:
631       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
632    case STREAM_UNIX_DEFAULT_ACL:
633    case STREAM_ACL_IRIX_DEFAULT_ACL:
634       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
635    }
636
637    return false;
638 }
639 #elif defined(HAVE_LINUX_OS)
640 static bool linux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
641 {
642    int len;
643
644    /*
645     * Read access ACLs for files, dirs and links
646     */
647    if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
648       return false;
649
650    if (len > 0) {
651       if (!send_acl_stream(jcr, STREAM_ACL_LINUX_ACCESS_ACL, len))
652          return false;
653    }
654
655    /*
656     * Directories can have default ACLs too
657     */
658    if (ff_pkt->type == FT_DIREND) {
659       if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
660          return false;
661
662       if (len > 0) {
663          if (!send_acl_stream(jcr, STREAM_ACL_LINUX_DEFAULT_ACL, len))
664             return false;
665       }
666    }
667
668    return true;
669 }
670
671 static bool linux_parse_acl_stream(JCR *jcr, int stream)
672 {
673    switch (stream) {
674    case STREAM_UNIX_ACCESS_ACL:
675    case STREAM_ACL_LINUX_ACCESS_ACL:
676       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
677    case STREAM_UNIX_DEFAULT_ACL:
678    case STREAM_ACL_LINUX_DEFAULT_ACL:
679       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
680    }
681
682    return false;
683 }
684 #elif defined(HAVE_OSF1_OS)
685 static bool tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
686 {
687    int len;
688
689    /*
690     * Read access ACLs for files, dirs and links
691     */
692    if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
693       return false;
694
695    if (len > 0) {
696       if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL, len))
697          return false;
698    }
699
700    /*
701     * Directories can have default ACLs too
702     */
703    if (ff_pkt->type == FT_DIREND) {
704       if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
705          return false;
706
707       if (len > 0) {
708          if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL, len))
709             return false;
710       }
711
712       /*
713        * Tru64 has next to BACL_TYPE_DEFAULT also BACL_TYPE_DEFAULT_DIR acls.
714        * This is an inherited acl for all subdirs.
715        * See http://www.helsinki.fi/atk/unix/dec_manuals/DOC_40D/AQ0R2DTE/DOCU_018.HTM
716        * Section 21.5 Default ACLs 
717        */
718       if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0)
719          return false;
720
721       if (len > 0) {
722          if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL, len))
723             return false;
724       }
725    }
726
727    return true;
728 }
729
730 static bool tru64_parse_acl_stream(JCR *jcr, int stream)
731 {
732    switch (stream) {
733    case STREAM_UNIX_ACCESS_ACL:
734    case STREAM_ACL_TRU64_ACCESS_ACL:
735       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
736    case STREAM_UNIX_DEFAULT_ACL:
737    case STREAM_ACL_TRU64_DEFAULT_ACL:
738       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
739    case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
740       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR);
741 }
742 #endif
743
744 #elif defined(HAVE_HPUX_OS)
745 #ifdef HAVE_SYS_ACL_H
746 #include <sys/acl.h>
747 #else
748 #error "configure failed to detect availability of sys/acl.h"
749 #endif
750
751 #include <acllib.h>
752
753 /*
754  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
755  * There is no need to store those acls as we already store the stat bits too.
756  */
757 static bool acl_is_trivial(int count, struct acl_entry *entries, struct stat sb)
758 {
759    int n;
760    struct acl_entry ace
761
762    for (n = 0; n < count; n++) {
763       ace = entries[n];
764
765       /*
766        * See if this acl just is the stat mode in acl form.
767        */
768       if (!((ace.uid == sb.st_uid && ace.gid == ACL_NSGROUP) ||
769             (ace.uid == ACL_NSUSER && ace.gid == sb.st_gid) ||
770             (ace.uid == ACL_NSUSER && ace.gid == ACL_NSGROUP)))
771          return false;
772    }
773
774    return true;
775 }
776
777 /*
778  * OS specific functions for handling different types of acl streams.
779  */
780 static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
781 {
782    int n, len;
783    struct acl_entry acls[NACLENTRIES];
784    char *acl_text;
785
786    if ((n = getacl(jcr->last_fname, 0, acls)) < 0) {
787       switch(errno) {
788 #if defined(BACL_ENOTSUP)
789       case BACL_ENOTSUP:
790          /*
791           * Not supported, just pretend there is nothing to see
792           */
793          pm_strcpy(jcr->acl_data, "");
794          return true;
795 #endif
796       default:
797          berrno be;
798          Jmsg2(jcr, M_ERROR, 0, _("getacl error on file \"%s\": ERR=%s\n"),
799             jcr->last_fname, be.bstrerror());
800          Dmsg2(100, "getacl error file=%s ERR=%s\n",  
801             jcr->last_fname, be.bstrerror());
802
803          pm_strcpy(jcr->acl_data, "");
804          return false;
805       }
806    }
807
808    if (n == 0) {
809       pm_strcpy(jcr->acl_data, "");
810       return true;
811    }
812
813    if ((n = getacl(jcr->last_fname, n, acls)) > 0) {
814       if (acl_is_trivial(n, acls, ff_pkt->statp)) {
815          /*
816           * The ACLs simply reflect the (already known) standard permissions
817           * So we don't send an ACL stream to the SD.
818           */
819          pm_strcpy(jcr->acl_data, "");
820          return true;
821       }
822
823       if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) {
824          len = pm_strcpy(jcr->acl_data, acl_text);
825          actuallyfree(acl_text);
826
827          return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY, len);
828       }
829
830       berrno be;
831       Jmsg2(jcr, M_ERROR, 0, _("acltostr error on file \"%s\": ERR=%s\n"),
832          jcr->last_fname, be.bstrerror());
833       Dmsg3(100, "acltostr error acl=%s file=%s ERR=%s\n",  
834          jcr->acl_data, jcr->last_fname, be.bstrerror());
835
836       return false;
837    }
838
839    return false;
840 }
841
842 static bool hpux_parse_acl_stream(JCR *jcr, int stream)
843 {
844    int n, stat;
845    struct acl_entry acls[NACLENTRIES];
846
847    n = strtoacl(jcr->acl_data, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
848    if (n <= 0) {
849       berrno be;
850       Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
851          jcr->last_fname, be.bstrerror());
852       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
853          jcr->acl_data, jcr->last_fname, be.bstrerror());
854
855       return false;
856    }
857    if (strtoacl(jcr->acl_data, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
858       berrno be;
859       Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
860          jcr->last_fname, be.bstrerror());
861       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
862          jcr->acl_data, jcr->last_fname, be.bstrerror());
863
864       return false;
865    }
866    /*
867     * Restore the ACLs, but don't complain about links which really should
868     * not have attributes, and the file it is linked to may not yet be restored.
869     * This is only true for the old acl streams as in the new implementation we
870     * don't save acls of symlinks (which cannot have acls anyhow)
871     */
872    if (setacl(jcr->last_fname, n, acls) != 0 && jcr->last_type != FT_LNK) {
873       berrno be;
874       Jmsg2(jcr, M_ERROR, 0, _("setacl error on file \"%s\": ERR=%s\n"),
875          jcr->last_fname, be.bstrerror());
876       Dmsg3(100, "setacl error acl=%s file=%s ERR=%s\n",  
877          jcr->acl_data, jcr->last_fname, be.bstrerror());
878
879       return false;
880    }
881
882    return true;
883 }
884
885 #elif defined(HAVE_SUN_OS)
886 #ifdef HAVE_SYS_ACL_H
887 #include <sys/acl.h>
888 #else
889 #error "configure failed to detect availability of sys/acl.h"
890 #endif
891
892 #if defined(HAVE_EXTENDED_ACL)
893 /*
894  * We define some internals of the Solaris acl libs here as those
895  * are not exposed yet. Probably because they want us to see the
896  * acls as opague data. But as we need to support different platforms
897  * and versions of Solaris we need to expose some data to be able
898  * to determine the type of acl used to stuff it into the correct
899  * data stream. I know this is far from portable, but maybe the
900  * propper interface is exposed later on and we can get ride of
901  * this kludge. Newer versions of Solaris include sys/acl_impl.h
902  * which has implementation details of acls, if thats included we
903  * don't have to define it ourself.
904  */
905 #if !defined(_SYS_ACL_IMPL_H)
906 typedef enum acl_type {
907    ACLENT_T = 0,
908    ACE_T = 1
909 } acl_type_t;
910 #endif
911
912 /*
913  * Two external references to functions in the libsec library function not in current include files.
914  */
915 extern "C" {
916 int acl_type(acl_t *);
917 char *acl_strerror(int);
918 }
919
920 /*
921  * As the new libsec interface with acl_totext and acl_fromtext also handles
922  * the old format from acltotext we can use the new functions even
923  * for acls retrieved and stored in the database with older fd versions. If the
924  * new interface is not defined (Solaris 9 and older we fall back to the old code)
925  */
926 static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
927 {
928    int acl_enabled, len, flags;
929    acl_t *aclp;
930    char *acl_text;
931    bool stream_status = false;
932
933    /*
934     * See if filesystem supports acls.
935     */
936    acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
937    switch (acl_enabled) {
938    case 0:
939       pm_strcpy(jcr->acl_data, "");
940
941       return true;
942    case -1:
943       Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"),
944          jcr->last_fname, strerror(errno));
945       Dmsg2(100, "pathconf error file=%s ERR=%s\n",  
946          jcr->last_fname, strerror(errno));
947
948       return false;
949    default:
950       break;
951    }
952
953    /*
954     * Get ACL info: don't bother allocating space if there is only a trivial ACL.
955     */
956    if (acl_get(jcr->last_fname, ACL_NO_TRIVIAL, &aclp) != 0) {
957       Jmsg2(jcr, M_ERROR, 0, _("acl_get error on file \"%s\": ERR=%s\n"),
958          jcr->last_fname, acl_strerror(errno));
959       Dmsg2(100, "acl_get error file=%s ERR=%s\n",  
960          jcr->last_fname, acl_strerror(errno));
961
962       return false;
963    }
964
965    if (aclp == NULL) {
966       /*
967        * The ACLs simply reflect the (already known) standard permissions
968        * So we don't send an ACL stream to the SD.
969        */
970       pm_strcpy(jcr->acl_data, "");
971       return true;
972    }
973
974 #if defined(ACL_SID_FMT)
975    /*
976     * New format flag added in newer Solaris versions.
977     */
978    flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
979 #else
980    flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
981 #endif /* ACL_SID_FMT */
982
983    if ((acl_text = acl_totext(aclp, flags)) != NULL) {
984       len = pm_strcpy(jcr->acl_data, acl_text);
985       actuallyfree(acl_text);
986
987       switch (acl_type(aclp)) {
988       case ACLENT_T:
989          stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT, len);
990          break;
991       case ACE_T:
992          stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE, len);
993          break;
994       default:
995          break;
996       }
997
998       acl_free(aclp);
999    }
1000
1001    return stream_status;
1002 }
1003
1004 static bool solaris_parse_acl_stream(JCR *jcr, int stream)
1005 {
1006    acl_t *aclp;
1007    int acl_enabled, error;
1008
1009    switch (stream) {
1010    case STREAM_UNIX_ACCESS_ACL:
1011    case STREAM_ACL_SOLARIS_ACLENT:
1012    case STREAM_ACL_SOLARIS_ACE:
1013       /*
1014        * First make sure the filesystem supports acls.
1015        */
1016       acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
1017       switch (acl_enabled) {
1018       case 0:
1019          Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without acl support\n"),
1020             jcr->last_fname);
1021
1022          return false;
1023       case -1:
1024          Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"),
1025             jcr->last_fname, strerror(errno));
1026          Dmsg3(100, "pathconf error acl=%s file=%s ERR=%s\n",  
1027             jcr->acl_data, jcr->last_fname, strerror(errno));
1028
1029          return false;
1030       default:
1031          /*
1032           * On a filesystem with ACL support make sure this particilar ACL type can be restored.
1033           */
1034          switch (stream) {
1035          case STREAM_ACL_SOLARIS_ACLENT:
1036             /*
1037              * An aclent can be restored on filesystems with _ACL_ACLENT_ENABLED or _ACL_ACE_ENABLED support.
1038              */
1039             if ((acl_enabled & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED)) == 0) {
1040                Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without aclent acl support\n"),
1041                   jcr->last_fname);
1042                return false;
1043             }
1044             break;
1045          case STREAM_ACL_SOLARIS_ACE:
1046             /*
1047              * An ace can only be restored on a filesystem with _ACL_ACE_ENABLED support.
1048              */
1049             if ((acl_enabled & _ACL_ACE_ENABLED) == 0) {
1050                Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without ace acl support\n"),
1051                   jcr->last_fname);
1052                return false;
1053             }
1054             break;
1055          default:
1056             /*
1057              * Stream id which doesn't describe the type of acl which is encoded.
1058              */
1059             break;
1060          }
1061          break;
1062       }
1063
1064       if ((error = acl_fromtext(jcr->acl_data, &aclp)) != 0) {
1065          Jmsg2(jcr, M_ERROR, 0, _("acl_fromtext error on file \"%s\": ERR=%s\n"),
1066             jcr->last_fname, acl_strerror(error));
1067          Dmsg3(100, "acl_fromtext error acl=%s file=%s ERR=%s\n",  
1068             jcr->acl_data, jcr->last_fname, acl_strerror(error));
1069          return false;
1070       }
1071
1072       /*
1073        * Validate that the conversion gave us the correct acl type.
1074        */
1075       switch (stream) {
1076       case STREAM_ACL_SOLARIS_ACLENT:
1077          if (acl_type(aclp) != ACLENT_T) {
1078             Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
1079                jcr->last_fname);
1080             return false;
1081          }
1082          break;
1083       case STREAM_ACL_SOLARIS_ACE:
1084          if (acl_type(aclp) != ACE_T) {
1085             Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
1086                jcr->last_fname);
1087             return false;
1088          }
1089          break;
1090       default:
1091          /*
1092           * Stream id which doesn't describe the type of acl which is encoded.
1093           */
1094          break;
1095       }
1096
1097       /*
1098        * Restore the ACLs, but don't complain about links which really should
1099        * not have attributes, and the file it is linked to may not yet be restored.
1100        * This is only true for the old acl streams as in the new implementation we
1101        * don't save acls of symlinks (which cannot have acls anyhow)
1102        */
1103       if ((error = acl_set(jcr->last_fname, aclp)) == -1 && jcr->last_type != FT_LNK) {
1104          Jmsg2(jcr, M_ERROR, 0, _("acl_set error on file \"%s\": ERR=%s\n"),
1105             jcr->last_fname, acl_strerror(error));
1106          Dmsg3(100, "acl_set error acl=%s file=%s ERR=%s\n",  
1107             jcr->acl_data, jcr->last_fname, acl_strerror(error));
1108
1109          acl_free(aclp);
1110          return false;
1111       }
1112
1113       acl_free(aclp);
1114       return true;
1115    default:
1116       return false;
1117    } /* end switch (stream) */
1118 }
1119
1120 #else /* HAVE_EXTENDED_ACL */
1121
1122 /*
1123  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
1124  * There is no need to store those acls as we already store the stat bits too.
1125  */
1126 static bool acl_is_trivial(int count, aclent_t *entries)
1127 {
1128    int n;
1129    aclent_t *ace;
1130
1131    for (n = 0; n < count; n++) {
1132       ace = &entries[n];
1133
1134       if (!(ace->a_type == USER_OBJ ||
1135             ace->a_type == GROUP_OBJ ||
1136             ace->a_type == OTHER_OBJ ||
1137             ace->a_type == CLASS_OBJ))
1138         return false;
1139    }
1140
1141    return true;
1142 }
1143
1144 /*
1145  * OS specific functions for handling different types of acl streams.
1146  */
1147 static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt);
1148 {
1149    int n, len;
1150    aclent_t *acls;
1151    char *acl_text;
1152
1153    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
1154    if (n < MIN_ACL_ENTRIES)
1155       return false;
1156
1157    acls = (aclent_t *)malloc(n * sizeof(aclent_t));
1158    if (acl(jcr->last_fname, GETACL, n, acls) == n) {
1159       if (acl_is_trivial(n, acls)) {
1160          /*
1161           * The ACLs simply reflect the (already known) standard permissions
1162           * So we don't send an ACL stream to the SD.
1163           */
1164          free(acls);
1165          pm_strcpy(jcr->acl_data, "");
1166          return true;
1167       }
1168
1169       if ((acl_text = acltotext(acls, n)) != NULL) {
1170          len = pm_strcpy(jcr->acl_data, acl_text);
1171          actuallyfree(acl_text);
1172          free(acls);
1173
1174          return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT, len);
1175       }
1176
1177       berrno be;
1178       Jmsg2(jcr, M_ERROR, 0, _("acltotext error on file \"%s\": ERR=%s\n"),
1179          jcr->last_fname, be.bstrerror());
1180       Dmsg3(100, "acltotext error acl=%s file=%s ERR=%s\n",  
1181          jcr->acl_data, jcr->last_fname, be.bstrerror());
1182    }
1183
1184    free(acls);
1185    return false;
1186 }
1187
1188 static bool solaris_parse_acl_stream(JCR *jcr, int stream)
1189 {
1190    int n;
1191    aclent_t *acls;
1192
1193    acls = aclfromtext(jcr->acl_data, &n);
1194    if (!acls) {
1195       berrno be;
1196       Jmsg2(jcr, M_ERROR, 0, _("aclfromtext error on file \"%s\": ERR=%s\n"),
1197          jcr->last_fname, be.bstrerror());
1198       Dmsg3(100, "aclfromtext error acl=%s file=%s ERR=%s\n",  
1199          jcr->acl_data, jcr->last_fname, be.bstrerror());
1200
1201       return false;
1202    }
1203
1204    /*
1205     * Restore the ACLs, but don't complain about links which really should
1206     * not have attributes, and the file it is linked to may not yet be restored.
1207     */
1208    if (acl(jcr->last_fname, SETACL, n, acls) == -1 && jcr->last_type != FT_LNK) {
1209       berrno be;
1210       Jmsg2(jcr, M_ERROR, 0, _("acl(SETACL) error on file \"%s\": ERR=%s\n"),
1211          jcr->last_fname, be.bstrerror());
1212       Dmsg3(100, "acl(SETACL) error acl=%s file=%s ERR=%s\n",  
1213          jcr->acl_data, jcr->last_fname, be.bstrerror());
1214       actuallyfree(acls);
1215
1216       return false;
1217    }
1218
1219    actuallyfree(acls);
1220    return true;
1221 }
1222
1223 #endif /* HAVE_EXTENDED_ACL */
1224 #endif /* HAVE_SUN_OS */
1225
1226 /*
1227  * Entry points when compiled with support for ACLs on a supported platform.
1228  */
1229
1230 /*
1231  * Read and send an ACL for the last encountered file.
1232  */
1233 bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
1234 {
1235    /*
1236     * Call the appropriate function, the ifdefs make sure the proper code is compiled.
1237     */
1238 #if defined(HAVE_AIX_OS)
1239    return aix_build_acl_streams(jcr, ff_pkt);
1240 #elif defined(HAVE_DARWIN_OS)
1241    return darwin_build_acl_streams(jcr, ff_pkt);
1242 #elif defined(HAVE_FREEBSD_OS)
1243    return freebsd_build_acl_streams(jcr, ff_pkt);
1244 #elif defined(HAVE_HPUX_OS)
1245    return hpux_build_acl_streams(jcr, ff_pkt);
1246 #elif defined(HAVE_IRIX_OS)
1247    return irix_build_acl_streams(jcr, ff_pkt);
1248 #elif defined(HAVE_LINUX_OS)
1249    return linux_build_acl_streams(jcr, ff_pkt);
1250 #elif defined(HAVE_OSF1_OS)
1251    return tru64_build_acl_streams(jcr, ff_pkt);
1252 #elif defined(HAVE_SUN_OS)
1253    return solaris_build_acl_streams(jcr, ff_pkt);
1254 #endif
1255 }
1256
1257 bool parse_acl_stream(JCR *jcr, int stream)
1258 {
1259    /*
1260     * Based on the stream being passed in dispatch to the right function
1261     * for parsing and restoring a specific acl. The platform determines
1262     * which streams are recognized and parsed and which are handled by
1263     * the default case and ignored. The old STREAM_UNIX_ACCESS_ACL and
1264     * STREAM_UNIX_DEFAULT_ACL is handled as a legacy stream by each function.
1265     * As only one of the platform defines is true per compile we never end
1266     * up with duplicate switch values.
1267     */
1268    switch (stream) {
1269 #if defined(HAVE_AIX_OS)
1270    case STREAM_UNIX_ACCESS_ACL:
1271    case STREAM_UNIX_DEFAULT_ACL:
1272    case STREAM_ACL_AIX_TEXT:
1273       return aix_parse_acl_stream(jcr, stream);
1274 #elif defined(HAVE_DARWIN_OS)
1275    case STREAM_UNIX_ACCESS_ACL:
1276    case STREAM_ACL_DARWIN_ACCESS_ACL:
1277       return darwin_parse_acl_stream(jcr, stream);
1278 #elif defined(HAVE_FREEBSD_OS)
1279    case STREAM_UNIX_ACCESS_ACL:
1280    case STREAM_UNIX_DEFAULT_ACL:
1281    case STREAM_ACL_FREEBSD_DEFAULT_ACL:
1282    case STREAM_ACL_FREEBSD_ACCESS_ACL:
1283       return freebsd_parse_acl_stream(jcr, stream);
1284 #elif defined(HAVE_HPUX_OS)
1285    case STREAM_UNIX_ACCESS_ACL:
1286    case STREAM_ACL_HPUX_ACL_ENTRY:
1287       return hpux_parse_acl_stream(jcr, stream);
1288 #elif defined(HAVE_IRIX_OS)
1289    case STREAM_UNIX_ACCESS_ACL:
1290    case STREAM_UNIX_DEFAULT_ACL:
1291    case STREAM_ACL_IRIX_DEFAULT_ACL:
1292    case STREAM_ACL_IRIX_ACCESS_ACL:
1293       return irix_parse_acl_stream(jcr, stream);
1294 #elif defined(HAVE_LINUX_OS)
1295    case STREAM_UNIX_ACCESS_ACL:
1296    case STREAM_UNIX_DEFAULT_ACL:
1297    case STREAM_ACL_LINUX_DEFAULT_ACL:
1298    case STREAM_ACL_LINUX_ACCESS_ACL:
1299       return linux_parse_acl_stream(jcr, stream);
1300 #elif defined(HAVE_OSF1_OS)
1301    case STREAM_UNIX_ACCESS_ACL:
1302    case STREAM_UNIX_DEFAULT_ACL:
1303    case STREAM_ACL_TRU64_DEFAULT_ACL:
1304    case STREAM_ACL_TRU64_ACCESS_ACL:
1305    case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
1306       return tru64_parse_acl_stream(jcr, stream);
1307 #elif defined(HAVE_SUN_OS)
1308    case STREAM_UNIX_ACCESS_ACL:
1309    case STREAM_ACL_SOLARIS_ACLENT:
1310 #if defined(HAVE_EXTENDED_ACL)
1311    case STREAM_ACL_SOLARIS_ACE:
1312 #endif
1313       return solaris_parse_acl_stream(jcr, stream);
1314 #endif
1315    default:
1316       /*
1317        * Issue a warning and discard the message. But pretend the restore was ok.
1318        */
1319       Qmsg2(jcr, M_WARNING, 0,
1320          _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"),
1321          jcr->last_fname, stream);
1322       return true;
1323    } /* end switch (stream) */
1324 }
1325 #endif