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