]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/acl.c
607c23d1e5e350134af22aa5309a3358d71aee87
[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 -1;
410    }
411
412    /*
413     * Handle errors gracefully.
414     */
415    switch (errno) {
416 #if defined(BACL_ENOTSUP)
417    case BACL_ENOTSUP:
418       /*
419        * Not supported, just pretend there is nothing to see
420        */
421       pm_strcpy(jcr->acl_data, "");
422       return 0;
423 #endif
424    default:
425       berrno be;
426       Jmsg2(jcr, M_ERROR, 0, _("acl_get_file error on file \"%s\": ERR=%s\n"),
427          jcr->last_fname, be.bstrerror());
428       Dmsg2(100, "acl_get_file error file=%s ERR=%s\n",  
429          jcr->last_fname, be.bstrerror());
430
431       pm_strcpy(jcr->acl_data, "");
432       return -1;
433    }
434 }
435
436 /*
437  * Generic wrapper around acl_set_file call.
438  */
439 static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype)
440 {
441    acl_t acl;
442    acl_type_t ostype;
443
444    /*
445     * If we get empty default ACLs, clear ACLs now
446     */
447    ostype = bac_to_os_acltype(acltype);
448    if (ostype == ACL_TYPE_DEFAULT && strlen(jcr->acl_data) == 0) {
449       if (acl_delete_def_file(jcr->last_fname) == 0) {
450          return true;
451       }
452       berrno be;
453       Jmsg2(jcr, M_ERROR, 0, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"),
454          jcr->last_fname, be.bstrerror());
455
456       return false;
457    }
458
459    acl = acl_from_text(jcr->acl_data);
460    if (acl == NULL) {
461       berrno be;
462       Jmsg2(jcr, M_ERROR, 0, _("acl_from_text error on file \"%s\": ERR=%s\n"),
463          jcr->last_fname, be.bstrerror());
464       Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n",  
465          jcr->acl_data, jcr->last_fname, be.bstrerror());
466
467       return false;
468    }
469
470    /*
471     * FreeBSD always fails acl_valid() - at least on valid input...
472     * As it does the right thing, given valid input, just ignore acl_valid().
473     */
474 #ifndef HAVE_FREEBSD_OS
475    if (acl_valid(acl) != 0) {
476       berrno be;
477       Jmsg2(jcr, M_ERROR, 0, _("ac_valid error on file \"%s\": ERR=%s\n"),
478          jcr->last_fname, be.bstrerror());
479       Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n",  
480          jcr->acl_data, jcr->last_fname, be.bstrerror());
481       acl_free(acl);
482
483       return false;
484    }
485 #endif
486
487    /*
488     * Restore the ACLs, but don't complain about links which really should
489     * not have attributes, and the file it is linked to may not yet be restored.
490     * This is only true for the old acl streams as in the new implementation we
491     * don't save acls of symlinks (which cannot have acls anyhow)
492     */
493    if (acl_set_file(jcr->last_fname, ostype, acl) != 0 && jcr->last_type != FT_LNK) {
494       berrno be;
495       Jmsg2(jcr, M_ERROR, 0, _("acl_set_file error on file \"%s\": ERR=%s\n"),
496          jcr->last_fname, be.bstrerror());
497       Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n",  
498          jcr->acl_data, jcr->last_fname, be.bstrerror());
499       acl_free(acl);
500
501       return false;
502    }
503    acl_free(acl);
504
505    return true;
506 }
507
508 /*
509  * OS specific functions for handling different types of acl streams.
510  */
511 #if defined(HAVE_DARWIN_OS)
512 static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
513 {
514 #if defined(ACL_TYPE_EXTENDED)
515    /*
516     * On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
517     * and acl_get_file (name, ACL_TYPE_DEFAULT)
518     * always return NULL / EINVAL.  There is no point in making
519     * these two useless calls.  The real ACL is retrieved through
520     * acl_get_file (name, ACL_TYPE_EXTENDED).
521     *
522     * Read access ACLs for files, dirs and links
523     */
524    if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0)
525       return false;
526 #else
527    /*
528     * Read access ACLs for files, dirs and links
529     */
530    if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
531       return false;
532
533    if (jcr->acl_data_len > 0) {
534       if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL))
535          return false;
536    }
537 #endif
538
539    return true;
540 }
541
542 static bool darwin_parse_acl_stream(JCR *jcr, int stream)
543 {
544    switch (stream) {
545    case STREAM_UNIX_ACCESS_ACL:
546    case STREAM_ACL_DARWIN_ACCESS_ACL:
547       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
548    }
549
550    return false;
551 }
552 #elif defined(HAVE_FREEBSD_OS)
553 static bool freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
554 {
555    /*
556     * Read access ACLs for files, dirs and links
557     */
558    if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
559       return false;
560
561    if (jcr->acl_data_len > 0) {
562       if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_ACCESS_ACL))
563          return false;
564    }
565
566    /*
567     * Directories can have default ACLs too
568     */
569    if (ff_pkt->type == FT_DIREND) {
570       if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
571          return false;
572
573       if (jcr->acl_data_len > 0) {
574          if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_DEFAULT_ACL))
575             return false;
576       }
577    }
578
579    return true;
580 }
581
582 static bool freebsd_parse_acl_stream(JCR *jcr, int stream)
583 {
584    switch (stream) {
585    case STREAM_UNIX_ACCESS_ACL:
586    case STREAM_ACL_FREEBSD_ACCESS_ACL:
587       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
588    case STREAM_UNIX_DEFAULT_ACL:
589    case STREAM_ACL_FREEBSD_DEFAULT_ACL:
590       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
591    }
592
593    return false;
594 }
595 #elif defined(HAVE_IRIX_OS)
596 static bool irix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
597 {
598    /*
599     * Read access ACLs for files, dirs and links
600     */
601    if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
602       return false;
603
604    if (jcr->acl_data_len > 0) {
605       if (!send_acl_stream(jcr, STREAM_ACL_IRIX_ACCESS_ACL))
606          return false;
607    }
608
609    /*
610     * Directories can have default ACLs too
611     */
612    if (ff_pkt->type == FT_DIREND) {
613       if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
614          return false;
615
616       if (jcr->acl_data_len > 0) {
617          if (!send_acl_stream(jcr, STREAM_ACL_IRIX_DEFAULT_ACL))
618             return false;
619       }
620    }
621
622    return true;
623 }
624
625 static bool irix_parse_acl_stream(JCR *jcr, int stream)
626 {
627    switch (stream) {
628    case STREAM_UNIX_ACCESS_ACL:
629    case STREAM_ACL_IRIX_ACCESS_ACL:
630       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
631    case STREAM_UNIX_DEFAULT_ACL:
632    case STREAM_ACL_IRIX_DEFAULT_ACL:
633       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
634    }
635
636    return false;
637 }
638 #elif defined(HAVE_LINUX_OS)
639 static bool linux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
640 {
641    /*
642     * Read access ACLs for files, dirs and links
643     */
644    if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
645       return false;
646
647    if (jcr->acl_data_len > 0) {
648       if (!send_acl_stream(jcr, STREAM_ACL_LINUX_ACCESS_ACL))
649          return false;
650    }
651
652    /*
653     * Directories can have default ACLs too
654     */
655    if (ff_pkt->type == FT_DIREND) {
656       if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
657          return false;
658
659       if (jcr->acl_data_len > 0) {
660          if (!send_acl_stream(jcr, STREAM_ACL_LINUX_DEFAULT_ACL))
661             return false;
662       }
663    }
664
665    return true;
666 }
667
668 static bool linux_parse_acl_stream(JCR *jcr, int stream)
669 {
670    switch (stream) {
671    case STREAM_UNIX_ACCESS_ACL:
672    case STREAM_ACL_LINUX_ACCESS_ACL:
673       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
674    case STREAM_UNIX_DEFAULT_ACL:
675    case STREAM_ACL_LINUX_DEFAULT_ACL:
676       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
677    }
678
679    return false;
680 }
681 #elif defined(HAVE_OSF1_OS)
682 static bool tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
683 {
684    /*
685     * Read access ACLs for files, dirs and links
686     */
687    if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
688       return false;
689
690    if (jcr->acl_data_len > 0) {
691       if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL))
692          return false;
693    }
694
695    /*
696     * Directories can have default ACLs too
697     */
698    if (ff_pkt->type == FT_DIREND) {
699       if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
700          return false;
701
702       if (jcr->acl_data_len > 0) {
703          if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL))
704             return false;
705       }
706
707       /*
708        * Tru64 has next to BACL_TYPE_DEFAULT also BACL_TYPE_DEFAULT_DIR acls.
709        * This is an inherited acl for all subdirs.
710        * See http://www.helsinki.fi/atk/unix/dec_manuals/DOC_40D/AQ0R2DTE/DOCU_018.HTM
711        * Section 21.5 Default ACLs 
712        */
713       if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0)
714          return false;
715
716       if (jcr->acl_data_len > 0) {
717          if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL))
718             return false;
719       }
720    }
721
722    return true;
723 }
724
725 static bool tru64_parse_acl_stream(JCR *jcr, int stream)
726 {
727    switch (stream) {
728    case STREAM_UNIX_ACCESS_ACL:
729    case STREAM_ACL_TRU64_ACCESS_ACL:
730       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
731    case STREAM_UNIX_DEFAULT_ACL:
732    case STREAM_ACL_TRU64_DEFAULT_ACL:
733       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
734    case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
735       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR);
736 }
737 #endif
738
739 #elif defined(HAVE_HPUX_OS)
740 #ifdef HAVE_SYS_ACL_H
741 #include <sys/acl.h>
742 #else
743 #error "configure failed to detect availability of sys/acl.h"
744 #endif
745
746 #include <acllib.h>
747
748 /*
749  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
750  * There is no need to store those acls as we already store the stat bits too.
751  */
752 static bool acl_is_trivial(int count, struct acl_entry *entries, struct stat sb)
753 {
754    int n;
755    struct acl_entry ace
756
757    for (n = 0; n < count; n++) {
758       ace = entries[n];
759
760       /*
761        * See if this acl just is the stat mode in acl form.
762        */
763       if (!((ace.uid == sb.st_uid && ace.gid == ACL_NSGROUP) ||
764             (ace.uid == ACL_NSUSER && ace.gid == sb.st_gid) ||
765             (ace.uid == ACL_NSUSER && ace.gid == ACL_NSGROUP)))
766          return false;
767    }
768
769    return true;
770 }
771
772 /*
773  * OS specific functions for handling different types of acl streams.
774  */
775 static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
776 {
777    int n;
778    struct acl_entry acls[NACLENTRIES];
779    char *acl_text;
780
781    if ((n = getacl(jcr->last_fname, 0, acls)) < 0) {
782       switch(errno) {
783 #if defined(BACL_ENOTSUP)
784       case BACL_ENOTSUP:
785          /*
786           * Not supported, just pretend there is nothing to see
787           */
788          pm_strcpy(jcr->acl_data, "");
789          return true;
790 #endif
791       default:
792          berrno be;
793          Jmsg2(jcr, M_ERROR, 0, _("getacl error on file \"%s\": ERR=%s\n"),
794             jcr->last_fname, be.bstrerror());
795          Dmsg2(100, "getacl error file=%s ERR=%s\n",  
796             jcr->last_fname, be.bstrerror());
797
798          pm_strcpy(jcr->acl_data, "");
799          return false;
800       }
801    }
802
803    if (n == 0) {
804       pm_strcpy(jcr->acl_data, "");
805       return true;
806    }
807
808    if ((n = getacl(jcr->last_fname, n, acls)) > 0) {
809       if (acl_is_trivial(n, acls, ff_pkt->statp)) {
810          /*
811           * The ACLs simply reflect the (already known) standard permissions
812           * So we don't send an ACL stream to the SD.
813           */
814          pm_strcpy(jcr->acl_data, "");
815          return true;
816       }
817
818       if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) {
819          jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
820          actuallyfree(acl_text);
821
822          return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY);
823       }
824
825       berrno be;
826       Jmsg2(jcr, M_ERROR, 0, _("acltostr error on file \"%s\": ERR=%s\n"),
827          jcr->last_fname, be.bstrerror());
828       Dmsg3(100, "acltostr error acl=%s file=%s ERR=%s\n",  
829          jcr->acl_data, jcr->last_fname, be.bstrerror());
830
831       return false;
832    }
833
834    return false;
835 }
836
837 static bool hpux_parse_acl_stream(JCR *jcr, int stream)
838 {
839    int n, stat;
840    struct acl_entry acls[NACLENTRIES];
841
842    n = strtoacl(jcr->acl_data, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
843    if (n <= 0) {
844       berrno be;
845       Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
846          jcr->last_fname, be.bstrerror());
847       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
848          jcr->acl_data, jcr->last_fname, be.bstrerror());
849
850       return false;
851    }
852    if (strtoacl(jcr->acl_data, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
853       berrno be;
854       Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
855          jcr->last_fname, be.bstrerror());
856       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
857          jcr->acl_data, jcr->last_fname, be.bstrerror());
858
859       return false;
860    }
861    /*
862     * Restore the ACLs, but don't complain about links which really should
863     * not have attributes, and the file it is linked to may not yet be restored.
864     * This is only true for the old acl streams as in the new implementation we
865     * don't save acls of symlinks (which cannot have acls anyhow)
866     */
867    if (setacl(jcr->last_fname, n, acls) != 0 && jcr->last_type != FT_LNK) {
868       berrno be;
869       Jmsg2(jcr, M_ERROR, 0, _("setacl error on file \"%s\": ERR=%s\n"),
870          jcr->last_fname, be.bstrerror());
871       Dmsg3(100, "setacl error acl=%s file=%s ERR=%s\n",  
872          jcr->acl_data, jcr->last_fname, be.bstrerror());
873
874       return false;
875    }
876
877    return true;
878 }
879
880 #elif defined(HAVE_SUN_OS)
881 #ifdef HAVE_SYS_ACL_H
882 #include <sys/acl.h>
883 #else
884 #error "configure failed to detect availability of sys/acl.h"
885 #endif
886
887 #if defined(HAVE_EXTENDED_ACL)
888 /*
889  * We define some internals of the Solaris acl libs here as those
890  * are not exposed yet. Probably because they want us to see the
891  * acls as opague data. But as we need to support different platforms
892  * and versions of Solaris we need to expose some data to be able
893  * to determine the type of acl used to stuff it into the correct
894  * data stream. I know this is far from portable, but maybe the
895  * propper interface is exposed later on and we can get ride of
896  * this kludge. Newer versions of Solaris include sys/acl_impl.h
897  * which has implementation details of acls, if thats included we
898  * don't have to define it ourself.
899  */
900 #if !defined(_SYS_ACL_IMPL_H)
901 typedef enum acl_type {
902    ACLENT_T = 0,
903    ACE_T = 1
904 } acl_type_t;
905 #endif
906
907 /*
908  * Two external references to functions in the libsec library function not in current include files.
909  */
910 extern "C" {
911 int acl_type(acl_t *);
912 char *acl_strerror(int);
913 }
914
915 /*
916  * As the new libsec interface with acl_totext and acl_fromtext also handles
917  * the old format from acltotext we can use the new functions even
918  * for acls retrieved and stored in the database with older fd versions. If the
919  * new interface is not defined (Solaris 9 and older we fall back to the old code)
920  */
921 static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
922 {
923    int acl_enabled, flags;
924    acl_t *aclp;
925    char *acl_text;
926    bool stream_status = false;
927    berrno be;
928
929    /*
930     * See if filesystem supports acls.
931     */
932    acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
933    switch (acl_enabled) {
934    case 0:
935       pm_strcpy(jcr->acl_data, "");
936
937       return true;
938    case -1:
939       Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"),
940          jcr->last_fname, be.bstrerror());
941       Dmsg2(100, "pathconf error file=%s ERR=%s\n",  
942          jcr->last_fname, be.bstrerror());
943
944       return false;
945    default:
946       break;
947    }
948
949    /*
950     * Get ACL info: don't bother allocating space if there is only a trivial ACL.
951     */
952    if (acl_get(jcr->last_fname, ACL_NO_TRIVIAL, &aclp) != 0) {
953       Jmsg2(jcr, M_ERROR, 0, _("acl_get error on file \"%s\": ERR=%s\n"),
954          jcr->last_fname, acl_strerror(errno));
955       Dmsg2(100, "acl_get error file=%s ERR=%s\n",  
956          jcr->last_fname, acl_strerror(errno));
957
958       return false;
959    }
960
961    if (!aclp) {
962       /*
963        * The ACLs simply reflect the (already known) standard permissions
964        * So we don't send an ACL stream to the SD.
965        */
966       pm_strcpy(jcr->acl_data, "");
967       return true;
968    }
969
970 #if defined(ACL_SID_FMT)
971    /*
972     * New format flag added in newer Solaris versions.
973     */
974    flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
975 #else
976    flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
977 #endif /* ACL_SID_FMT */
978
979    if ((acl_text = acl_totext(aclp, flags)) != NULL) {
980       jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
981       actuallyfree(acl_text);
982
983       switch (acl_type(aclp)) {
984       case ACLENT_T:
985          stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
986          break;
987       case ACE_T:
988          stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE);
989          break;
990       default:
991          break;
992       }
993
994       acl_free(aclp);
995    }
996
997    return stream_status;
998 }
999
1000 static bool solaris_parse_acl_stream(JCR *jcr, int stream)
1001 {
1002    acl_t *aclp;
1003    int acl_enabled, error;
1004    berrno be;
1005
1006    switch (stream) {
1007    case STREAM_UNIX_ACCESS_ACL:
1008    case STREAM_ACL_SOLARIS_ACLENT:
1009    case STREAM_ACL_SOLARIS_ACE:
1010       /*
1011        * First make sure the filesystem supports acls.
1012        */
1013       acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
1014       switch (acl_enabled) {
1015       case 0:
1016          Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without acl support\n"),
1017             jcr->last_fname);
1018
1019          return false;
1020       case -1:
1021          Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"),
1022             jcr->last_fname, be.bstrerror());
1023          Dmsg3(100, "pathconf error acl=%s file=%s ERR=%s\n",  
1024             jcr->acl_data, jcr->last_fname, be.bstrerror());
1025
1026          return false;
1027       default:
1028          /*
1029           * On a filesystem with ACL support make sure this particilar ACL type can be restored.
1030           */
1031          switch (stream) {
1032          case STREAM_ACL_SOLARIS_ACLENT:
1033             /*
1034              * An aclent can be restored on filesystems with _ACL_ACLENT_ENABLED or _ACL_ACE_ENABLED support.
1035              */
1036             if ((acl_enabled & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED)) == 0) {
1037                Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without aclent acl support\n"),
1038                   jcr->last_fname);
1039                return false;
1040             }
1041             break;
1042          case STREAM_ACL_SOLARIS_ACE:
1043             /*
1044              * An ace can only be restored on a filesystem with _ACL_ACE_ENABLED support.
1045              */
1046             if ((acl_enabled & _ACL_ACE_ENABLED) == 0) {
1047                Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without ace acl support\n"),
1048                   jcr->last_fname);
1049                return false;
1050             }
1051             break;
1052          default:
1053             /*
1054              * Stream id which doesn't describe the type of acl which is encoded.
1055              */
1056             break;
1057          }
1058          break;
1059       }
1060
1061       if ((error = acl_fromtext(jcr->acl_data, &aclp)) != 0) {
1062          Jmsg2(jcr, M_ERROR, 0, _("acl_fromtext error on file \"%s\": ERR=%s\n"),
1063             jcr->last_fname, acl_strerror(error));
1064          Dmsg3(100, "acl_fromtext error acl=%s file=%s ERR=%s\n",  
1065             jcr->acl_data, jcr->last_fname, acl_strerror(error));
1066          return false;
1067       }
1068
1069       /*
1070        * Validate that the conversion gave us the correct acl type.
1071        */
1072       switch (stream) {
1073       case STREAM_ACL_SOLARIS_ACLENT:
1074          if (acl_type(aclp) != ACLENT_T) {
1075             Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
1076                jcr->last_fname);
1077             return false;
1078          }
1079          break;
1080       case STREAM_ACL_SOLARIS_ACE:
1081          if (acl_type(aclp) != ACE_T) {
1082             Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
1083                jcr->last_fname);
1084             return false;
1085          }
1086          break;
1087       default:
1088          /*
1089           * Stream id which doesn't describe the type of acl which is encoded.
1090           */
1091          break;
1092       }
1093
1094       /*
1095        * Restore the ACLs, but don't complain about links which really should
1096        * not have attributes, and the file it is linked to may not yet be restored.
1097        * This is only true for the old acl streams as in the new implementation we
1098        * don't save acls of symlinks (which cannot have acls anyhow)
1099        */
1100       if ((error = acl_set(jcr->last_fname, aclp)) == -1 && jcr->last_type != FT_LNK) {
1101          Jmsg2(jcr, M_ERROR, 0, _("acl_set error on file \"%s\": ERR=%s\n"),
1102             jcr->last_fname, acl_strerror(error));
1103          Dmsg3(100, "acl_set error acl=%s file=%s ERR=%s\n",  
1104             jcr->acl_data, jcr->last_fname, acl_strerror(error));
1105
1106          acl_free(aclp);
1107          return false;
1108       }
1109
1110       acl_free(aclp);
1111       return true;
1112    default:
1113       return false;
1114    } /* end switch (stream) */
1115 }
1116
1117 #else /* HAVE_EXTENDED_ACL */
1118
1119 /*
1120  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
1121  * There is no need to store those acls as we already store the stat bits too.
1122  */
1123 static bool acl_is_trivial(int count, aclent_t *entries)
1124 {
1125    int n;
1126    aclent_t *ace;
1127
1128    for (n = 0; n < count; n++) {
1129       ace = &entries[n];
1130
1131       if (!(ace->a_type == USER_OBJ ||
1132             ace->a_type == GROUP_OBJ ||
1133             ace->a_type == OTHER_OBJ ||
1134             ace->a_type == CLASS_OBJ))
1135         return false;
1136    }
1137
1138    return true;
1139 }
1140
1141 /*
1142  * OS specific functions for handling different types of acl streams.
1143  */
1144 static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt);
1145 {
1146    int n;
1147    aclent_t *acls;
1148    char *acl_text;
1149
1150    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
1151    if (n < MIN_ACL_ENTRIES)
1152       return false;
1153
1154    acls = (aclent_t *)malloc(n * sizeof(aclent_t));
1155    if (acl(jcr->last_fname, GETACL, n, acls) == n) {
1156       if (acl_is_trivial(n, acls)) {
1157          /*
1158           * The ACLs simply reflect the (already known) standard permissions
1159           * So we don't send an ACL stream to the SD.
1160           */
1161          free(acls);
1162          pm_strcpy(jcr->acl_data, "");
1163          return true;
1164       }
1165
1166       if ((acl_text = acltotext(acls, n)) != NULL) {
1167          jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text);
1168          actuallyfree(acl_text);
1169          free(acls);
1170
1171          return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
1172       }
1173
1174       berrno be;
1175       Jmsg2(jcr, M_ERROR, 0, _("acltotext error on file \"%s\": ERR=%s\n"),
1176          jcr->last_fname, be.bstrerror());
1177       Dmsg3(100, "acltotext error acl=%s file=%s ERR=%s\n",  
1178          jcr->acl_data, jcr->last_fname, be.bstrerror());
1179    }
1180
1181    free(acls);
1182    return false;
1183 }
1184
1185 static bool solaris_parse_acl_stream(JCR *jcr, int stream)
1186 {
1187    int n;
1188    aclent_t *acls;
1189
1190    acls = aclfromtext(jcr->acl_data, &n);
1191    if (!acls) {
1192       berrno be;
1193       Jmsg2(jcr, M_ERROR, 0, _("aclfromtext error on file \"%s\": ERR=%s\n"),
1194          jcr->last_fname, be.bstrerror());
1195       Dmsg3(100, "aclfromtext error acl=%s file=%s ERR=%s\n",  
1196          jcr->acl_data, jcr->last_fname, be.bstrerror());
1197
1198       return false;
1199    }
1200
1201    /*
1202     * Restore the ACLs, but don't complain about links which really should
1203     * not have attributes, and the file it is linked to may not yet be restored.
1204     */
1205    if (acl(jcr->last_fname, SETACL, n, acls) == -1 && jcr->last_type != FT_LNK) {
1206       berrno be;
1207       Jmsg2(jcr, M_ERROR, 0, _("acl(SETACL) error on file \"%s\": ERR=%s\n"),
1208          jcr->last_fname, be.bstrerror());
1209       Dmsg3(100, "acl(SETACL) error acl=%s file=%s ERR=%s\n",  
1210          jcr->acl_data, jcr->last_fname, be.bstrerror());
1211       actuallyfree(acls);
1212
1213       return false;
1214    }
1215
1216    actuallyfree(acls);
1217    return true;
1218 }
1219
1220 #endif /* HAVE_EXTENDED_ACL */
1221 #endif /* HAVE_SUN_OS */
1222
1223 /*
1224  * Entry points when compiled with support for ACLs on a supported platform.
1225  */
1226
1227 /*
1228  * Read and send an ACL for the last encountered file.
1229  */
1230 bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
1231 {
1232    /*
1233     * Call the appropriate function, the ifdefs make sure the proper code is compiled.
1234     */
1235 #if defined(HAVE_AIX_OS)
1236    return aix_build_acl_streams(jcr, ff_pkt);
1237 #elif defined(HAVE_DARWIN_OS)
1238    return darwin_build_acl_streams(jcr, ff_pkt);
1239 #elif defined(HAVE_FREEBSD_OS)
1240    return freebsd_build_acl_streams(jcr, ff_pkt);
1241 #elif defined(HAVE_HPUX_OS)
1242    return hpux_build_acl_streams(jcr, ff_pkt);
1243 #elif defined(HAVE_IRIX_OS)
1244    return irix_build_acl_streams(jcr, ff_pkt);
1245 #elif defined(HAVE_LINUX_OS)
1246    return linux_build_acl_streams(jcr, ff_pkt);
1247 #elif defined(HAVE_OSF1_OS)
1248    return tru64_build_acl_streams(jcr, ff_pkt);
1249 #elif defined(HAVE_SUN_OS)
1250    return solaris_build_acl_streams(jcr, ff_pkt);
1251 #endif
1252 }
1253
1254 bool parse_acl_stream(JCR *jcr, int stream)
1255 {
1256    /*
1257     * Based on the stream being passed in dispatch to the right function
1258     * for parsing and restoring a specific acl. The platform determines
1259     * which streams are recognized and parsed and which are handled by
1260     * the default case and ignored. The old STREAM_UNIX_ACCESS_ACL and
1261     * STREAM_UNIX_DEFAULT_ACL is handled as a legacy stream by each function.
1262     * As only one of the platform defines is true per compile we never end
1263     * up with duplicate switch values.
1264     */
1265    switch (stream) {
1266 #if defined(HAVE_AIX_OS)
1267    case STREAM_UNIX_ACCESS_ACL:
1268    case STREAM_UNIX_DEFAULT_ACL:
1269    case STREAM_ACL_AIX_TEXT:
1270       return aix_parse_acl_stream(jcr, stream);
1271 #elif defined(HAVE_DARWIN_OS)
1272    case STREAM_UNIX_ACCESS_ACL:
1273    case STREAM_ACL_DARWIN_ACCESS_ACL:
1274       return darwin_parse_acl_stream(jcr, stream);
1275 #elif defined(HAVE_FREEBSD_OS)
1276    case STREAM_UNIX_ACCESS_ACL:
1277    case STREAM_UNIX_DEFAULT_ACL:
1278    case STREAM_ACL_FREEBSD_DEFAULT_ACL:
1279    case STREAM_ACL_FREEBSD_ACCESS_ACL:
1280       return freebsd_parse_acl_stream(jcr, stream);
1281 #elif defined(HAVE_HPUX_OS)
1282    case STREAM_UNIX_ACCESS_ACL:
1283    case STREAM_ACL_HPUX_ACL_ENTRY:
1284       return hpux_parse_acl_stream(jcr, stream);
1285 #elif defined(HAVE_IRIX_OS)
1286    case STREAM_UNIX_ACCESS_ACL:
1287    case STREAM_UNIX_DEFAULT_ACL:
1288    case STREAM_ACL_IRIX_DEFAULT_ACL:
1289    case STREAM_ACL_IRIX_ACCESS_ACL:
1290       return irix_parse_acl_stream(jcr, stream);
1291 #elif defined(HAVE_LINUX_OS)
1292    case STREAM_UNIX_ACCESS_ACL:
1293    case STREAM_UNIX_DEFAULT_ACL:
1294    case STREAM_ACL_LINUX_DEFAULT_ACL:
1295    case STREAM_ACL_LINUX_ACCESS_ACL:
1296       return linux_parse_acl_stream(jcr, stream);
1297 #elif defined(HAVE_OSF1_OS)
1298    case STREAM_UNIX_ACCESS_ACL:
1299    case STREAM_UNIX_DEFAULT_ACL:
1300    case STREAM_ACL_TRU64_DEFAULT_ACL:
1301    case STREAM_ACL_TRU64_ACCESS_ACL:
1302    case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
1303       return tru64_parse_acl_stream(jcr, stream);
1304 #elif defined(HAVE_SUN_OS)
1305    case STREAM_UNIX_ACCESS_ACL:
1306    case STREAM_ACL_SOLARIS_ACLENT:
1307 #if defined(HAVE_EXTENDED_ACL)
1308    case STREAM_ACL_SOLARIS_ACE:
1309 #endif
1310       return solaris_parse_acl_stream(jcr, stream);
1311 #endif
1312    default:
1313       /*
1314        * Issue a warning and discard the message. But pretend the restore was ok.
1315        */
1316       Qmsg2(jcr, M_WARNING, 0,
1317          _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"),
1318          jcr->last_fname, stream);
1319       return true;
1320    } /* end switch (stream) */
1321 }
1322 #endif