2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Major refactoring of ACL code written by:
22 * Radosław Korzeniewski, MMXVI
23 * radoslaw@korzeniewski.net, radekk@inteos.pl
24 * Inteos Sp. z o.o. http://www.inteos.pl/
30 #include "bacl_linux.h"
32 #if defined(HAVE_LINUX_OS)
34 /* check if ACL support is enabled */
38 * Define the supported ACL streams for this OS
40 static const int os_acl_streams[] = {
41 STREAM_XACL_LINUX_ACCESS,
45 static const int os_default_acl_streams[] = {
46 STREAM_XACL_LINUX_DEFAULT,
51 * OS specific constructor
53 BACL_Linux::BACL_Linux(){
54 set_acl_streams(os_acl_streams, os_default_acl_streams);
58 * Translates Bacula internal acl representation into
62 * bacltype - internal Bacula acl type (BACL_type)
64 * acl_type_t - os dependent acl type
65 * when failed - ACL_TYPE_NONE is returned
67 acl_type_t BACL_Linux::get_acltype(BACL_type bacltype){
72 case BACL_TYPE_ACCESS:
73 acltype = ACL_TYPE_ACCESS;
75 case BACL_TYPE_DEFAULT:
76 acltype = ACL_TYPE_DEFAULT;
80 * sanity check for acl's not supported by OS
82 acltype = (acl_type_t)ACL_TYPE_NONE;
89 * Counts a number of acl entries
94 * int - number of entries in acl object
95 * when no acl entry available or any error then return zero '0'
97 int BACL_Linux::acl_nrentries(acl_t acl){
100 acl_entry_t aclentry;
103 rc = acl_get_entry(acl, ACL_FIRST_ENTRY, &aclentry);
106 rc = acl_get_entry(acl, ACL_NEXT_ENTRY, &aclentry);
113 * Checks if acl is simple.
115 * acl is simple if it has only the following entries:
123 * true - when acl object is simple
124 * false - when acl object is not simple
126 bool BACL_Linux::acl_issimple(acl_t acl){
128 acl_entry_t aclentry;
132 rc = acl_get_entry(acl, ACL_FIRST_ENTRY, &aclentry);
134 if (acl_get_tag_type(aclentry, &acltag) < 0){
138 * Check for ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER to find out.
140 if (acltag != ACL_USER_OBJ &&
141 acltag != ACL_GROUP_OBJ &&
142 acltag != ACL_OTHER){
145 rc = acl_get_entry(acl, ACL_NEXT_ENTRY, &aclentry);
151 * Perform OS specific ACL backup
153 * in/out - check API at bacl.h
155 bRC_BACL BACL_Linux::os_backup_acl (JCR *jcr, FF_PKT *ff_pkt){
156 return generic_backup_acl(jcr, ff_pkt);
160 * Perform OS specific ACL restore
162 * in/out - check API at bacl.h
164 bRC_BACL BACL_Linux::os_restore_acl (JCR *jcr, int stream, char *content, uint32_t length){
165 return generic_restore_acl(jcr, stream);
169 * Low level OS specific runtime to get ACL data from file. The ACL data is set in internal content buffer.
171 * in/out - check API at bacl.h
173 bRC_BACL BACL_Linux::os_get_acl(JCR *jcr, BACL_type bacltype){
178 bRC_BACL rc = bRC_BACL_ok;
180 /* check input data */
182 return bRC_BACL_inval;
185 acltype = get_acltype(bacltype);
186 acl = acl_get_file(jcr->last_fname, acltype);
189 Dmsg1(400, "OS_ACL read from file: %s\n",jcr->last_fname);
190 if (acl_nrentries(acl) == 0){
194 /* check for simple ACL which correspond to standard permissions only */
195 if (bacltype == BACL_TYPE_ACCESS && acl_issimple(acl)){
199 if ((acltext = acl_to_text(acl, NULL)) != NULL){
200 set_content(acltext);
208 Mmsg2(jcr->errmsg, _("acl_to_text error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
209 Dmsg2(100, "acl_to_text error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
217 /* fs does not support acl, skip it */
218 Dmsg0(400, "Wow, ACL is not supported on this filesystem\n");
219 clear_flag(BACL_FLAG_NATIVE);
224 /* Some real error */
225 Mmsg2(jcr->errmsg, _("acl_get_file error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
226 Dmsg2(100, "acl_get_file error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
237 * it is a bit of hardcore to clear a poolmemory with a NULL pointer,
238 * but it is working, hehe :)
239 * you may ask why it is working? it is simple, a pm_strcpy function is handling
240 * a null pointer with a substitiution of empty string.
247 * Low level OS specific runtime to set ACL data on file
249 * in/out - check API at bacl.h
251 bRC_BACL BACL_Linux::os_set_acl(JCR *jcr, BACL_type bacltype, char *content, uint32_t length){
256 /* check input data */
257 if (jcr == NULL || content == NULL){
258 return bRC_BACL_inval;
261 acl = acl_from_text(content);
265 Mmsg2(jcr->errmsg, _("acl_from_text error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
266 Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n", content, jcr->last_fname, be.bstrerror());
267 return bRC_BACL_error;
270 if (acl_valid(acl) != 0){
273 Mmsg2(jcr->errmsg, _("acl_valid error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
274 Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n", content, jcr->last_fname, be.bstrerror());
276 return bRC_BACL_error;
279 /* handle different acl types for Linux */
280 acltype = get_acltype(bacltype);
281 if (acltype == ACL_TYPE_DEFAULT && length == 0){
282 /* delete ACl from file when no acl data available for default acl's */
283 if (acl_delete_def_file(jcr->last_fname) == 0){
293 * If the filesystem reports it doesn't support acl's we clear the
294 * BACL_FLAG_NATIVE flag so we skip ACL restores on all other files
295 * on the same filesystem. The BACL_FLAG_NATIVE flag gets set again
296 * when we change from one filesystem to an other.
298 clear_flag(BACL_FLAG_NATIVE);
299 Mmsg(jcr->errmsg, _("acl_delete_def_file error on file \"%s\": filesystem doesn't support ACLs\n"), jcr->last_fname);
300 return bRC_BACL_error;
302 Mmsg2(jcr->errmsg, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
303 return bRC_BACL_error;
308 * Restore the ACLs, but don't complain about links which really should
309 * not have attributes, and the file it is linked to may not yet be restored.
310 * This is only true for the old acl streams as in the new implementation we
311 * don't save acls of symlinks (which cannot have acls anyhow)
313 if (acl_set_file(jcr->last_fname, acltype, acl) != 0 && jcr->last_type != FT_LNK){
321 * If the filesystem reports it doesn't support ACLs we clear the
322 * BACL_FLAG_NATIVE flag so we skip ACL restores on all other files
323 * on the same filesystem. The BACL_FLAG_NATIVE flag gets set again
324 * when we change from one filesystem to an other.
326 clear_flag(BACL_FLAG_NATIVE);
327 Mmsg(jcr->errmsg, _("acl_set_file error on file \"%s\": filesystem doesn't support ACLs\n"), jcr->last_fname);
328 Dmsg2(100, "acl_set_file error acl=%s file=%s filesystem doesn't support ACLs\n", content, jcr->last_fname);
330 return bRC_BACL_error;
332 Mmsg2(jcr->errmsg, _("acl_set_file error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
333 Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n", content, jcr->last_fname, be.bstrerror());
335 return bRC_BACL_error;
342 #endif /* HAVE_ACL */
344 #endif /* HAVE_LINUX_OS */