1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18  */
19 /**
20  * Major refactoring of ACL code written by:
21  *
22  *  Radosław Korzeniewski, MMXVI
23  *  radoslaw@korzeniewski.net, radekk@inteos.pl
24  *  Inteos Sp. z o.o. http://www.inteos.pl/
25  *
26  *
27  * A specialized class to handle ACL in Bacula Enterprise.
28  * The runtime consist of two parts:
29  * 1. OS independent class: BACL
30  * 2. OS dependent subclass: BACL_*
31  *
32  * OS dependent subclasses are available for the following OS:
33  *   - Darwin (OSX)
34  *   - FreeBSD (POSIX and NFSv4/ZFS acls)
35  *   - Linux
36  *   - Solaris (POSIX and NFSv4/ZFS acls)
37  *
38  * OS dependent subclasses in progress:
39  *   - AIX (pre-5.3 and post 5.3 acls, acl_get and aclx_get interface)
40  *   - HPUX
41  *   - IRIX
42  *   - Tru64
43  *
44  * OS independent class support AFS acls using the pioctl interface.
45  *
46  * ACLs are saved in OS native text format provided by acl(3) API and uses
47  * different streams for all different platforms.
48  * Above behavior is a backward compatibility with previous Bacula implementation
49  * we need to maintain.
50  *
51  * During OS specific implementation of BACL you need to implement a following methods:
52  *
53  * [bacl] - indicates bacl function/method to call
54  * [os] - indicates OS specific function, which could be different on specific OS
55  *        (we use a Linux API calls as an example)
56  *
57  * ::os_get_acl(JCR *jcr, BACL_type bacltype)
58  *
59  *   1. get binary form of the acl - acl_get_file[os]
60  *   2. check if acl is trivial if required - call acl_issimple[bacl]
61  *   3. translate binary form into text representation - acl_to_text[os]
62  *   4. save acl text into content - set_content[bacl]
63  *   5. if acl not supported on filesystem - call clear_flag(BACL_FLAG_NATIVE)[bacl]
64  *
65  * ::os_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
66  *
67  *   1. call os_get_acl[bacl] for all supported ACL_TYPES
68  *   2. call send_acl_stream[bacl] for all supported ACL_STREAMS
69  *
70  * ::os_set_acl(JCR *jcr, BACL_type bacltype, char *content, uint32_t length)
71  *
72  *   1. prepare acl binary form from text representation stored in content - acl_from_text[os]
73  *   2. set acl on file - acl_set_file[os]
74  *   3. if acl not supported on filesystem, clear_flag(BACL_FLAG_NATIVE)
75  *
76  * ::os_restore_acl (JCR *jcr, int stream, char *content, uint32_t length)
77  *
78  *   1. call os_set_acl for all supported ACL_TYPES
79  */
80 
81 #include "bacula.h"
82 #include "filed.h"
83 #include "fd_plugins.h"
84 
85 /* check if ACL support is enabled */
86 #if defined(HAVE_ACL)
87 
88 /*
89  * This is a constructor of the base BACL class which is OS independent
90  *
91  * - for initialization it uses ::init()
92  *
93  */
BACL()94 BACL::BACL (){
95    init();
96 };
97 
98 /*
99  * This is a destructor of the BACL class
100  */
~BACL()101 BACL::~BACL (){
102    free_pool_memory(content);
103 };
104 
105 /*
106  * Initialization routine
107  * - initializes all variables to required status
108  * - allocates required memory
109  */
init()110 void BACL::init(){
111 #if defined(HAVE_ACL)
112    acl_ena = TRUE;
113 #else
114    acl_ena = FALSE;
115 #endif
116 
117    /* generic variables */
118    flags = BACL_FLAG_NONE;
119    current_dev = 0;
120    content = get_pool_memory(PM_BSOCK);   /* it is better to have a 4k buffer */
121    content_len = 0;
122    acl_nr_errors = 0;
123    acl_streams = NULL;
124    default_acl_streams = NULL;
125 };
126 
127 /*
128  * Enables ACL handling in runtime, could be disabled with disable_acl
129  *    when ACL is not configured then cannot change status
130  */
enable_acl()131 void BACL::enable_acl(){
132 #if defined(HAVE_ACL)
133    acl_ena = TRUE;
134 #endif
135 };
136 
137 /*
138  * Disables ACL handling in runtime, could be enabled with enable_acl
139  *    when ACL is configured
140  */
disable_acl()141 void BACL::disable_acl(){
142    acl_ena = FALSE;
143 };
144 
145 /*
146  * Copies a text into a content variable and sets a content_len respectively
147  *
148  * in:
149  *    text - a standard null terminated string
150  * out:
151  *    pointer to content variable to use externally
152  */
set_content(char * text)153 POOLMEM * BACL::set_content(char *text){
154    content_len = pm_strcpy(&content, text);
155    if (content_len > 0){
156       /* count the nul terminated char */
157       content_len++;
158    }
159    // Dmsg2(400, "BACL::set_content: %p %i\n", text, content_len);
160    return content;
161 };
162 
163 /*
164  * Copies a data with length of len into a content variable
165  *
166  * in:
167  *    data - data pointer to copy into content buffer
168  * out:
169  *    pointer to content variable to use externally
170  */
set_content(char * data,int len)171 POOLMEM * BACL::set_content(char *data, int len){
172    content_len = pm_memcpy(&content, data, len);
173    return content;
174 };
175 
176 /*
177  * Check if we changed the device,
178  * if so setup a flags
179  *
180  * in:
181  *    jcr - Job Control Record
182  * out:
183  *    bRC_BACL_ok - change of device checked and finish successful
184  *    bRC_BACL_error - encountered error
185  *    bRC_BACL_skip - cannot verify device - no file found
186  *    bRC_BACL_inval - invalid input data
187  */
check_dev(JCR * jcr)188 bRC_BACL BACL::check_dev (JCR *jcr){
189 
190    int lst;
191    struct stat st;
192 
193    /* sanity check of input variables */
194    if (jcr == NULL || jcr->last_fname == NULL){
195       return bRC_BACL_inval;
196    }
197 
198    lst = lstat(jcr->last_fname, &st);
199    switch (lst){
200       case -1: {
201          berrno be;
202          switch (errno){
203          case ENOENT:
204             return bRC_BACL_skip;
205          default:
206             Mmsg2(jcr->errmsg, _("Unable to stat file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
207             Dmsg2(100, "Unable to stat file \"%s\": ERR=%s\n", jcr->last_fname, be.bstrerror());
208             return bRC_BACL_error;
209          }
210          break;
211       }
212       case 0:
213          break;
214    }
215 
216    check_dev(jcr, st.st_dev);
217 
218    return bRC_BACL_ok;
219 };
220 
221 /*
222  * Check if we changed the device, if so setup a flags
223  *
224  * in:
225  *    jcr - Job Control Record
226  * out:
227  *    internal flags status set
228  */
check_dev(JCR * jcr,uint32_t dev)229 void BACL::check_dev (JCR *jcr, uint32_t dev){
230 
231    /* sanity check of input variables */
232    if (jcr == NULL || jcr->last_fname == NULL){
233       return;
234    }
235 
236    if (current_dev != dev){
237       flags = BACL_FLAG_NONE;
238 #if defined(HAVE_AFS_ACL)
239       /* handle special fs: AFS */
240       if (fstype_equals(jcr->last_fname, "afs")){
241          set_flag(BACL_FLAG_AFS);
242       } else {
243          set_flag(BACL_FLAG_NATIVE);
244       }
245 #else
246       set_flag(BACL_FLAG_NATIVE);
247 #endif
248       current_dev = dev;
249    }
250 };
251 
252 /*
253  * It sends a stream located in this->content to Storage Daemon, so the main Bacula
254  * backup loop is free from this. It sends a header followed by data.
255  *
256  * in:
257  *    jcr - Job Control Record
258  *    stream - a stream number to save
259  * out:
260  *    bRC_BACL_inval - when supplied variables are incorrect
261  *    bRC_BACL_fatal - when we can't send data to the SD
262  *    bRC_BACL_ok - send finish without errors
263  */
send_acl_stream(JCR * jcr,int stream)264 bRC_BACL BACL::send_acl_stream(JCR *jcr, int stream){
265 
266    BSOCK * sd;
267    POOLMEM * msgsave;
268 #ifdef FD_NO_SEND_TEST
269    return bRC_BACL_ok;
270 #endif
271 
272    /* sanity check of input variables */
273    if (jcr == NULL || jcr->store_bsock == NULL){
274       return bRC_BACL_inval;
275    }
276    if (content_len <= 0){
277       return bRC_BACL_ok;
278    }
279 
280    sd = jcr->store_bsock;
281    /* send header */
282    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)){
283       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
284       return bRC_BACL_fatal;
285    }
286 
287    /* send the buffer to the storage daemon */
288    Dmsg1(400, "Backing up ACL: %i\n", content_len);
289 #if 0
290    POOL_MEM tmp(PM_FNAME);
291    pm_memcpy(tmp, content, content_len);
292    Dmsg2(400, "Backing up ACL: (%i) <%s>\n", strlen(tmp.addr()), tmp.c_str());
293 #endif
294    msgsave = sd->msg;
295    sd->msg = content;
296    sd->msglen = content_len;
297    if (!sd->send()){
298       sd->msg = msgsave;
299       sd->msglen = 0;
300       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
301       return bRC_BACL_fatal;
302    }
303 
304    jcr->JobBytes += sd->msglen;
305    sd->msg = msgsave;
306    if (!sd->signal(BNET_EOD)){
307       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
308       return bRC_BACL_fatal;
309    }
310 
311    Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
312    return bRC_BACL_ok;
313 };
314 
315 /*
316  * The main public backup method for ACL
317  *
318  * in:
319  *    jcr - Job Control Record
320  *    ff_pkt - file backup record
321  * out:
322  *    bRC_BACL_fatal - when ACL backup is not compiled in Bacula
323  *    bRC_BACL_ok - backup finish without problems
324  *    bRC_BACL_error - when you can't backup acl data because some error
325  */
backup_acl(JCR * jcr,FF_PKT * ff_pkt)326 bRC_BACL BACL::backup_acl (JCR *jcr, FF_PKT *ff_pkt)
327 {
328 #if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL)
329    Jmsg(jcr, M_FATAL, 0, "ACL backup requested but not configured in Bacula.\n");
330    return bRC_BACL_fatal;
331 #else
332    /* sanity check of input variables and verify if engine is enabled */
333    if (acl_ena && jcr != NULL && ff_pkt != NULL){
334       /* acl engine enabled, proceed */
335       bRC_BACL rc;
336 
337       jcr->errmsg[0] = 0;
338       /* check if we have a plugin generated backup */
339       if (ff_pkt->cmd_plugin){
340          rc = backup_plugin_acl(jcr, ff_pkt);
341       } else {
342          /* Check for aclsupport flag and no acl request for link */
343          if (!(ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK)){
344             return bRC_BACL_ok;
345          }
346 
347          check_dev(jcr, ff_pkt->statp.st_dev);
348 
349 #if defined(HAVE_AFS_ACL)
350          if (flags & BACL_FLAG_AFS){
351             Dmsg0(400, "make AFS ACL call\n");
352             rc = afs_backup_acl(jcr, ff_pkt);
353             goto bail_out;
354          }
355 #endif
356 
357 #if defined(HAVE_ACL)
358          if (flags & BACL_FLAG_NATIVE){
359             Dmsg0(400, "make Native ACL call\n");
360             rc = os_backup_acl(jcr, ff_pkt);
361          } else {
362             /* skip acl backup */
363             return bRC_BACL_ok;
364          }
365 #endif
366       }
367 #if defined(HAVE_AFS_ACL)
368    bail_out:
369 #endif
370       if (rc == bRC_BACL_error){
371          if (acl_nr_errors < ACL_MAX_ERROR_PRINT_PER_JOB){
372             if (!jcr->errmsg[0]){
373                Jmsg(jcr, M_WARNING, 0, "No OS ACL configured.\n");
374             } else {
375                Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
376             }
377             inc_acl_errors();
378          }
379          return bRC_BACL_ok;
380       }
381       return rc;
382    }
383    return bRC_BACL_ok;
384 #endif
385 };
386 
387 /*
388  * The main public restore method for ACL
389  *
390  * in:
391  *    jcr - Job Control Record
392  *    stream - a backup stream type number to restore_acl
393  *    data - a pointer to the data stream to restore
394  *    length - a data stream length
395  * out:
396  *    bRC_BACL_fatal - when ACL restore is not compiled in Bacula
397  *    bRC_BACL_ok - restore finish without problems
398  *    bRC_BACL_error - when you can't restore a stream because some error
399  */
restore_acl(JCR * jcr,int stream,char * data,uint32_t length)400 bRC_BACL BACL::restore_acl (JCR *jcr, int stream, char *data, uint32_t length)
401 {
402 #if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL)
403    Jmsg(jcr, M_FATAL, 0, "ACL restore requested but not configured in Bacula.\n");
404    return bRC_BACL_fatal;
405 #else
406    /* sanity check of input variables and verify if engine is enabled */
407    if (acl_ena && jcr != NULL && data != NULL){
408       /* acl engine enabled, proceed */
409       int a;
410       bRC_BACL rc;
411 
412       /* check_dev supported on real fs only */
413       if (stream != STREAM_XACL_PLUGIN_ACL){
414          rc = check_dev(jcr);
415 
416          switch (rc){
417             case bRC_BACL_skip:
418                return bRC_BACL_ok;
419             case bRC_BACL_ok:
420                break;
421             default:
422                return rc;
423          }
424       }
425 
426       /* copy a data into a content buffer */
427       set_content(data, length);
428 
429       switch (stream){
430 #if defined(HAVE_AFS_ACL)
431          case STREAM_BACL_AFS_TEXT:
432             if (flags & BACL_FLAG_AFS){
433                return afs_restore_acl(jcr, stream);
434             } else {
435                /*
436                 * Increment error count but don't log an error again for the same filesystem.
437                 */
438                inc_acl_errors();
439                return bRC_BACL_ok;
440             }
441 #endif
442 #if defined(HAVE_ACL)
443          case STREAM_UNIX_ACCESS_ACL:
444          case STREAM_UNIX_DEFAULT_ACL:
445             if (flags & BACL_FLAG_NATIVE){
446                return os_restore_acl(jcr, stream, content, content_len);
447             } else {
448                inc_acl_errors();
449                return bRC_BACL_ok;
450             }
451             break;
452          case STREAM_XACL_PLUGIN_ACL:
453             return restore_plugin_acl(jcr);
454          default:
455             if (flags & BACL_FLAG_NATIVE){
456                Dmsg0(400, "make Native ACL call\n");
457                for (a = 0; acl_streams[a] > 0; a++){
458                   if (acl_streams[a] == stream){
459                      return os_restore_acl(jcr, stream, content, content_len);
460                   }
461                }
462                for (a = 0; default_acl_streams[a] > 0; a++){
463                   if (default_acl_streams[a] == stream){
464                      return os_restore_acl(jcr, stream, content, content_len);
465                   }
466                }
467             } else {
468                inc_acl_errors();
469                return bRC_BACL_ok;
470             }
471             break;
472 #else
473          default:
474             break;
475 #endif
476       }
477       /* cannot find a valid stream to support */
478       Qmsg2(jcr, M_WARNING, 0, _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"), jcr->last_fname, stream);
479       return bRC_BACL_error;
480    }
481    return bRC_BACL_ok;
482 #endif
483 };
484 
485 /*
486  * Performs a generic ACL backup using OS specific methods for
487  * getting acl data from file
488  *
489  * in:
490  *    jcr - Job Control Record
491  *    ff_pkt - file to backup control package
492  * out:
493  *    bRC_BACL_ok - backup of acl's was successful
494  *    bRC_BACL_fatal - was an error during acl backup
495  */
generic_backup_acl(JCR * jcr,FF_PKT * ff_pkt)496 bRC_BACL BACL::generic_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
497 {
498    /* sanity check of input variables */
499    if (jcr == NULL || ff_pkt == NULL){
500       return bRC_BACL_inval;
501    }
502 
503    if (os_get_acl(jcr, BACL_TYPE_ACCESS) == bRC_BACL_fatal){
504       /* XXX: check if os_get_acl return fatal and decide what to do when error is returned */
505       return bRC_BACL_fatal;
506    }
507 
508    if (content_len > 0){
509       if (send_acl_stream(jcr, acl_streams[0]) == bRC_BACL_fatal){
510          return bRC_BACL_fatal;
511       }
512    }
513 
514    if (ff_pkt->type == FT_DIREND){
515       if (os_get_acl(jcr, BACL_TYPE_DEFAULT) == bRC_BACL_fatal){
516          return bRC_BACL_fatal;
517       }
518       if (content_len > 0){
519          if (send_acl_stream(jcr, default_acl_streams[0]) == bRC_BACL_fatal){
520             return bRC_BACL_fatal;
521          }
522       }
523    }
524    return bRC_BACL_ok;
525 };
526 
527 /*
528  * Performs a generic ACL restore using OS specific methods for
529  * setting acl data on file.
530  *
531  * in:
532  *    jcr - Job Control Record
533  *    stream - a stream number to restore
534  * out:
535  *    bRC_BACL_ok - restore of acl's was successful
536  *    bRC_BACL_error - was an error during acl restore
537  *    bRC_BACL_fatal - was a fatal error during acl restore or input data
538  *                     is invalid
539  */
generic_restore_acl(JCR * jcr,int stream)540 bRC_BACL BACL::generic_restore_acl (JCR *jcr, int stream){
541 
542    unsigned int count;
543 
544    /* sanity check of input variables */
545    if (jcr == NULL){
546       return bRC_BACL_inval;
547    }
548 
549    switch (stream){
550       case STREAM_UNIX_ACCESS_ACL:
551          return os_set_acl(jcr, BACL_TYPE_ACCESS, content, content_len);
552       case STREAM_UNIX_DEFAULT_ACL:
553          return os_set_acl(jcr, BACL_TYPE_DEFAULT, content, content_len);
554       default:
555          for (count = 0; acl_streams[count] > 0; count++){
556             if (acl_streams[count] == stream){
557                return os_set_acl(jcr, BACL_TYPE_ACCESS, content, content_len);
558             }
559          }
560          for (count = 0; default_acl_streams[count] > 0; count++){
561             if (default_acl_streams[count] == stream){
562                return os_set_acl(jcr, BACL_TYPE_DEFAULT, content, content_len);
563             }
564          }
565          break;
566    }
567    return bRC_BACL_error;
568 };
569 
570 /*
571  * Perform a generic ACL backup using a plugin. It calls the plugin API to
572  * get required acl data from plugin.
573  *
574  * in:
575  *    jcr - Job Control Record
576  *    ff_pkt - file to backup control package
577  * out:
578  *    bRC_BACL_ok - backup of acls was successful
579  *    bRC_BACL_fatal - was an error during acl backup
580  */
backup_plugin_acl(JCR * jcr,FF_PKT * ff_pkt)581 bRC_BACL BACL::backup_plugin_acl (JCR *jcr, FF_PKT *ff_pkt)
582 {
583    int status;
584    char *data;
585 
586    /* sanity check of input variables */
587    if (jcr == NULL || ff_pkt == NULL){
588       return bRC_BACL_inval;
589    }
590 
591    while ((status = plugin_backup_acl(jcr, ff_pkt, &data)) > 0){
592       /* data is a plugin buffer which contains data to backup
593        * and status is a length of the buffer when > 0 */
594       set_content(data, status);
595       if (send_acl_stream(jcr, STREAM_XACL_PLUGIN_ACL) == bRC_BACL_fatal){
596          return bRC_BACL_fatal;
597       }
598    }
599    if (status < 0){
600       /* error */
601       return bRC_BACL_error;
602    }
603 
604    return bRC_BACL_ok;
605 };
606 
607 /*
608  * Perform a generic ACL restore using a plugin. It calls the plugin API to
609  * send acl data to plugin.
610  *
611  * in:
612  *    jcr - Job Control Record
613  *    stream - a stream number to restore
614  * out:
615  *    bRC_BACL_ok - restore of acls was successful
616  *    bRC_BACL_error - was an error during acls restore
617  *    bRC_BACL_fatal - was a fatal error during acl restore or input data
618  *                     is invalid
619  */
restore_plugin_acl(JCR * jcr)620 bRC_BACL BACL::restore_plugin_acl (JCR *jcr)
621 {
622    /* sanity check of input variables */
623    if (jcr == NULL){
624       return bRC_BACL_inval;
625    }
626 
627    if (!plugin_restore_acl(jcr, content, content_len)){
628       /* error */
629       return bRC_BACL_error;
630    }
631 
632    return bRC_BACL_ok;
633 }
634 
635 /*
636  * Initialize variables acl_streams and default_acl_streams for a specified OS.
637  * The rutine should be called from object instance constructor
638  *
639  * in:
640  *    pacl - acl streams supported for specific OS
641  *    pacl_def - default (directory) acl streams supported for specific OS
642  */
set_acl_streams(const int * pacl,const int * pacl_def)643 void BACL::set_acl_streams (const int *pacl, const int *pacl_def){
644 
645    acl_streams = pacl;
646    default_acl_streams = pacl_def;
647 };
648 
649 #if defined(HAVE_AFS_ACL)
650 #if defined(HAVE_AFS_AFSINT_H) && defined(HAVE_AFS_VENUS_H)
651 #include <afs/afsint.h>
652 #include <afs/venus.h>
653 #else
654 #error "configure failed to detect availability of afs/afsint.h and/or afs/venus.h"
655 #endif
656 
657 /*
658  * External references to functions in the libsys library function not in current include files.
659  */
660 extern "C" {
661 long pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow);
662 }
663 
664 /*
665  * Backup ACL data of AFS
666  *
667  * in:
668  *    jcr - Job Control Record
669  *    ff_pkt - file backup record
670  * out:
671  *    bRC_BACL_inval - input variables are invalid (NULL)
672  *    bRC_BACL_ok - backup finish without problems
673  *    bRC_BACL_error - when you can't backup acl data because some error
674  */
afs_backup_acl(JCR * jcr,FF_PKT * ff_pkt)675 bRC_BACL BACL::afs_backup_acl (JCR *jcr, FF_PKT *ff_pkt){
676 
677    int rc;
678    struct ViceIoctl vip;
679    char data[BUFSIZ];
680 
681    /* sanity check of input variables */
682    if (jcr == NULL || ff_pkt == NULL){
683       return bRC_BACL_inval;
684    }
685 
686    /* AFS ACLs can only be set on a directory, so no need to try other files */
687    if (ff_pkt->type != FT_DIREND){
688       return bRC_BACL_ok;
689    }
690 
691    vip.in = NULL;
692    vip.in_size = 0;
693    vip.out = data;
694    vip.out_size = BUFSIZE;
695    memset(data, 0, BUFSIZE);
696 
697    if ((rc = pioctl(jcr->last_fname, VIOCGETAL, &vip, 0)) < 0){
698       berrno be;
699 
700       Mmsg2(jcr->errmsg, _("pioctl VIOCGETAL error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
701       Dmsg2(100, "pioctl VIOCGETAL error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
702       return bRC_BACL_error;
703    }
704    set_content(data);
705    return send_acl_stream(jcr, STREAM_BACL_AFS_TEXT);
706 };
707 
708 /*
709  * Restore ACL data of AFS
710  * in:
711  *    jcr - Job Control Record
712  *    stream - a backup stream type number to restore_acl
713  * out:
714  *    bRC_BACL_inval - input variables are invalid (NULL)
715  *    bRC_BACL_ok - backup finish without problems
716  *    bRC_BACL_error - when you can't backup acl data because some error
717  */
afs_restore_acl(JCR * jcr,int stream)718 bRC_BACL BACL::afs_restore_acl (JCR *jcr, int stream){
719 
720    int rc;
721    struct ViceIoctl vip;
722 
723    /* sanity check of input variables */
724    if (jcr == NULL || ff_pkt == NULL){
725       return bRC_BACL_inval;
726    }
727 
728    vip.in = content;
729    vip.in_size = content_len;
730    vip.out = NULL;
731    vip.out_size = 0;
732 
733    if ((rc = pioctl(jcr->last_fname, VIOCSETAL, &vip, 0)) < 0){
734       berrno be;
735 
736       Mmsg2(jcr->errmsg, _("pioctl VIOCSETAL error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
737       Dmsg2(100, "pioctl VIOCSETAL error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
738 
739       return bRC_BACL_error;
740    }
741    return bRC_BACL_ok;
742 };
743 #endif /* HAVE_AFS_ACL */
744 
745 #include "bacl_osx.h"
746 #include "bacl_linux.h"
747 #include "bacl_freebsd.h"
748 #include "bacl_solaris.h"
749 // #include "bacl_aix.h"
750 
751 /*
752  * Creating the correct instance of the BACL for a supported OS
753  */
new_bacl()754 void *new_bacl()
755 {
756 #if   defined(HAVE_DARWIN_OS)
757    return new BACL_OSX();
758 #elif defined(HAVE_LINUX_OS)
759    return new BACL_Linux();
760 #elif defined(HAVE_FREEBSD_OS)
761    return new BACL_FreeBSD();
762 #elif defined(HAVE_HURD_OS)
763    return new BACL_Hurd();
764 #elif defined(HAVE_AIX_OS)
765    return new BACL_AIX();
766 #elif defined(HAVE_IRIX_OS)
767    return new BACL_IRIX();
768 #elif defined(HAVE_OSF1_OS)
769    return new BACL_OSF1();
770 #elif defined(HAVE_SUN_OS)
771    return new BACL_Solaris();
772 #else
773    return NULL;
774 #endif
775 };
776 
777 #endif /* HAVE_ACL */
778