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