]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/bacl.c
Update ACL/XATTR code and define new ACL/XATTR API for Plugins.
[bacula/bacula] / bacula / src / filed / bacl.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 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  */
94 BACL::BACL (){
95    init();
96 };
97
98 /*
99  * This is a destructor of the BACL class
100  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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                for (a = 0; acl_streams[a] > 0; a++){
457                   if (acl_streams[a] == stream){
458                      return os_restore_acl(jcr, stream, content, content_len);
459                   }
460                }
461                for (a = 0; default_acl_streams[a] > 0; a++){
462                   if (default_acl_streams[a] == stream){
463                      return os_restore_acl(jcr, stream, content, content_len);
464                   }
465                }
466             } else {
467                inc_acl_errors();
468                return bRC_BACL_ok;
469             }
470             break;
471 #else
472          default:
473             break;
474 #endif
475       }
476       /* cannot find a valid stream to support */
477       Qmsg2(jcr, M_WARNING, 0, _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"), jcr->last_fname, stream);
478       return bRC_BACL_error;
479    }
480    return bRC_BACL_ok;
481 #endif
482 };
483
484 /*
485  * Performs a generic ACL backup using OS specific methods for
486  * getting acl data from file
487  *
488  * in:
489  *    jcr - Job Control Record
490  *    ff_pkt - file to backup control package
491  * out:
492  *    bRC_BACL_ok - backup of acl's was successful
493  *    bRC_BACL_fatal - was an error during acl backup
494  */
495 bRC_BACL BACL::generic_backup_acl (JCR *jcr, FF_PKT *ff_pkt)
496 {
497    /* sanity check of input variables */
498    if (jcr == NULL || ff_pkt == NULL){
499       return bRC_BACL_inval;
500    }
501
502    if (os_get_acl(jcr, BACL_TYPE_ACCESS) == bRC_BACL_fatal){
503       /* XXX: check if os_get_acl return fatal and decide what to do when error is returned */
504       return bRC_BACL_fatal;
505    }
506
507    if (content_len > 0){
508       if (send_acl_stream(jcr, acl_streams[0]) == bRC_BACL_fatal){
509          return bRC_BACL_fatal;
510       }
511    }
512
513    if (ff_pkt->type == FT_DIREND){
514       if (os_get_acl(jcr, BACL_TYPE_DEFAULT) == bRC_BACL_fatal){
515          return bRC_BACL_fatal;
516       }
517       if (content_len > 0){
518          if (send_acl_stream(jcr, default_acl_streams[0]) == bRC_BACL_fatal){
519             return bRC_BACL_fatal;
520          }
521       }
522    }
523    return bRC_BACL_ok;
524 };
525
526 /*
527  * Performs a generic ACL restore using OS specific methods for
528  * setting acl data on file.
529  *
530  * in:
531  *    jcr - Job Control Record
532  *    stream - a stream number to restore
533  * out:
534  *    bRC_BACL_ok - restore of acl's was successful
535  *    bRC_BACL_error - was an error during acl restore
536  *    bRC_BACL_fatal - was a fatal error during acl restore or input data
537  *                     is invalid
538  */
539 bRC_BACL BACL::generic_restore_acl (JCR *jcr, int stream){
540
541    unsigned int count;
542
543    /* sanity check of input variables */
544    if (jcr == NULL){
545       return bRC_BACL_inval;
546    }
547
548    switch (stream){
549       case STREAM_UNIX_ACCESS_ACL:
550          return os_set_acl(jcr, BACL_TYPE_ACCESS, content, content_len);
551       case STREAM_UNIX_DEFAULT_ACL:
552          return os_set_acl(jcr, BACL_TYPE_DEFAULT, content, content_len);
553       default:
554          for (count = 0; acl_streams[count] > 0; count++){
555             if (acl_streams[count] == stream){
556                return os_set_acl(jcr, BACL_TYPE_ACCESS, content, content_len);
557             }
558          }
559          for (count = 0; default_acl_streams[count] > 0; count++){
560             if (default_acl_streams[count] == stream){
561                return os_set_acl(jcr, BACL_TYPE_DEFAULT, content, content_len);
562             }
563          }
564          break;
565    }
566    return bRC_BACL_error;
567 };
568
569 /*
570  * Perform a generic ACL backup using a plugin. It calls the plugin API to
571  * get required acl data from plugin.
572  *
573  * in:
574  *    jcr - Job Control Record
575  *    ff_pkt - file to backup control package
576  * out:
577  *    bRC_BACL_ok - backup of acls was successful
578  *    bRC_BACL_fatal - was an error during acl backup
579  */
580 bRC_BACL BACL::backup_plugin_acl (JCR *jcr, FF_PKT *ff_pkt)
581 {
582    int status;
583    char *data;
584
585    /* sanity check of input variables */
586    if (jcr == NULL || ff_pkt == NULL){
587       return bRC_BACL_inval;
588    }
589
590    while ((status = plugin_backup_acl(jcr, ff_pkt, &data)) > 0){
591       /* data is a plugin buffer which contains data to backup
592        * and status is a length of the buffer when > 0 */
593       set_content(data, status);
594       if (send_acl_stream(jcr, STREAM_XACL_PLUGIN_ACL) == bRC_BACL_fatal){
595          return bRC_BACL_fatal;
596       }
597    }
598    if (status < 0){
599       /* error */
600       return bRC_BACL_error;
601    }
602
603    return bRC_BACL_ok;
604 };
605
606 /*
607  * Perform a generic ACL restore using a plugin. It calls the plugin API to
608  * send acl data to plugin.
609  *
610  * in:
611  *    jcr - Job Control Record
612  *    stream - a stream number to restore
613  * out:
614  *    bRC_BACL_ok - restore of acls was successful
615  *    bRC_BACL_error - was an error during acls restore
616  *    bRC_BACL_fatal - was a fatal error during acl restore or input data
617  *                     is invalid
618  */
619 bRC_BACL BACL::restore_plugin_acl (JCR *jcr)
620 {
621    /* sanity check of input variables */
622    if (jcr == NULL){
623       return bRC_BACL_inval;
624    }
625
626    if (!plugin_restore_acl(jcr, content, content_len)){
627       /* error */
628       return bRC_BACL_error;
629    }
630
631    return bRC_BACL_ok;
632 }
633
634 /*
635  * Initialize variables acl_streams and default_acl_streams for a specified OS.
636  * The rutine should be called from object instance constructor
637  *
638  * in:
639  *    pacl - acl streams supported for specific OS
640  *    pacl_def - default (directory) acl streams supported for specific OS
641  */
642 void BACL::set_acl_streams (const int *pacl, const int *pacl_def){
643
644    acl_streams = pacl;
645    default_acl_streams = pacl_def;
646 };
647
648 #if defined(HAVE_AFS_ACL)
649 #if defined(HAVE_AFS_AFSINT_H) && defined(HAVE_AFS_VENUS_H)
650 #include <afs/afsint.h>
651 #include <afs/venus.h>
652 #else
653 #error "configure failed to detect availability of afs/afsint.h and/or afs/venus.h"
654 #endif
655
656 /*
657  * External references to functions in the libsys library function not in current include files.
658  */
659 extern "C" {
660 long pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow);
661 }
662
663 /*
664  * Backup ACL data of AFS
665  *
666  * in:
667  *    jcr - Job Control Record
668  *    ff_pkt - file backup record
669  * out:
670  *    bRC_BACL_inval - input variables are invalid (NULL)
671  *    bRC_BACL_ok - backup finish without problems
672  *    bRC_BACL_error - when you can't backup acl data because some error
673  */
674 bRC_BACL BACL::afs_backup_acl (JCR *jcr, FF_PKT *ff_pkt){
675
676    int rc;
677    struct ViceIoctl vip;
678    char data[BUFSIZ];
679
680    /* sanity check of input variables */
681    if (jcr == NULL || ff_pkt == NULL){
682       return bRC_BACL_inval;
683    }
684
685    /* AFS ACLs can only be set on a directory, so no need to try other files */
686    if (ff_pkt->type != FT_DIREND){
687       return bRC_BACL_ok;
688    }
689
690    vip.in = NULL;
691    vip.in_size = 0;
692    vip.out = data;
693    vip.out_size = BUFSIZE;
694    memset(data, 0, BUFSIZE);
695
696    if ((rc = pioctl(jcr->last_fname, VIOCGETAL, &vip, 0)) < 0){
697       berrno be;
698
699       Mmsg2(jcr->errmsg, _("pioctl VIOCGETAL error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
700       Dmsg2(100, "pioctl VIOCGETAL error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
701       return bRC_BACL_error;
702    }
703    set_content(data);
704    return send_acl_stream(jcr, STREAM_BACL_AFS_TEXT);
705 };
706
707 /*
708  * Restore ACL data of AFS
709  * in:
710  *    jcr - Job Control Record
711  *    stream - a backup stream type number to restore_acl
712  * out:
713  *    bRC_BACL_inval - input variables are invalid (NULL)
714  *    bRC_BACL_ok - backup finish without problems
715  *    bRC_BACL_error - when you can't backup acl data because some error
716  */
717 bRC_BACL BACL::afs_restore_acl (JCR *jcr, int stream){
718
719    int rc;
720    struct ViceIoctl vip;
721
722    /* sanity check of input variables */
723    if (jcr == NULL || ff_pkt == NULL){
724       return bRC_BACL_inval;
725    }
726
727    vip.in = content;
728    vip.in_size = content_len;
729    vip.out = NULL;
730    vip.out_size = 0;
731
732    if ((rc = pioctl(jcr->last_fname, VIOCSETAL, &vip, 0)) < 0){
733       berrno be;
734
735       Mmsg2(jcr->errmsg, _("pioctl VIOCSETAL error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
736       Dmsg2(100, "pioctl VIOCSETAL error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
737
738       return bRC_BACL_error;
739    }
740    return bRC_BACL_ok;
741 };
742 #endif /* HAVE_AFS_ACL */
743
744 #include "bacl_osx.h"
745 #include "bacl_linux.h"
746 #include "bacl_freebsd.h"
747 #include "bacl_solaris.h"
748 // #include "bacl_aix.h"
749
750 /*
751  * Creating the correct instance of the BACL for a supported OS
752  */
753 void *new_bacl()
754 {
755 #if   defined(HAVE_DARWIN_OS)
756    return new BACL_OSX();
757 #elif defined(HAVE_LINUX_OS)
758    return new BACL_Linux();
759 #elif defined(HAVE_FREEBSD_OS)
760    return new BACL_FreeBSD();
761 #elif defined(HAVE_HURD_OS)
762    return new BACL_Hurd();
763 #elif defined(HAVE_AIX_OS)
764    return new BACL_AIX();
765 #elif defined(HAVE_IRIX_OS)
766    return new BACL_IRIX();
767 #elif defined(HAVE_OSF1_OS)
768    return new BACL_OSF1();
769 #elif defined(HAVE_SUN_OS)
770    return new BACL_Solaris();
771 #else
772    return NULL;
773 #endif
774 };
775
776 #endif /* HAVE_ACL */