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